ページ 1 / 1
DLLファイルが読み込まれない?
Posted: 2009年11月24日(火) 21:53
by ジャーニー
お久しぶりです
大学の研究でとあるハードウェアを使うことになり、その製品のライブラリを導入しようとしているのですがうまくいきません。
おそらくDLLが正常に読み込まれていないだろうと思います。
同梱ファイルの中身は単純で、使っているものの最低限の動作確認のため、初期化を実行しようとしているだけです。
test.cpp
#include <iostream>
#include "DxLib.h"
#include "HAROC2D.hpp"
/* ドライバの初期化 */
bool initializeDriver( void )
{
int status;
status = HAROC_InitDriver( 10+1 ); /* ドライバの初期化 */
if( status != 0 ) {
/* 初期化失敗処理 */
return false;
}
else {
/* 初期化成功処理 */
return true;
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
if( !HAROC2manager::loadDLL() ) return 0;/* HAROC2.DLLのロード */
if( !initializeDriver() ) return 0;
HAROC2manager::freeDLL(); /* HAROC2.DLLの解放 */
return 0;
}
上のソースのHAROC_InitDriverでエラーがでており、エラーは
「Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.」
とでております。調べたところDLLを読み込んだあと正常に関数呼び出しだされていないのではないかという感じです。
hppファイルはDLLの読み込みと解放を記述しているだけです。
hppとDLLは製品に同梱されていたものです。
どなたかわかる方がいましたら回答をお願いします
Re:DLLファイルが読み込まれない?
Posted: 2009年11月24日(火) 22:19
by 御津凪
その DLL を使ったことが無いので正確ではないかもしれませんが、
そのようなランタイムエラーは 関数の呼び出し規約 が異なる場合に出ることがあります。
製品にマニュアルなどがある場合、何か呼び出し規約についての記述が無いか確かめてみてください。
基本、呼び出し規約の指定は、ヘッダ側の関数宣言でするものなのですが、指定がされていない場合、
コンパイラオプションで指定した呼び出し規約(VC++ なら通常は __cdecl)を指定することになります。
Re:DLLファイルが読み込まれない?
Posted: 2009年11月24日(火) 22:27
by ジャーニー
このDLLは製品付属のものなので一般的にはないものです
呼び出し規約と決めるというのは初耳なのですが、どのように指定すればいいのでしょうか?
Re:DLLファイルが読み込まれない?
Posted: 2009年11月24日(火) 22:40
by 御津凪
VC++ の IDE であれば、
プロジェクトのプロパティから、「構成プロパティ」「C/C++」、「詳細」、「呼び出し規約」の順で設定にたどり着きます。
ここの設定を変更していって、DLL の関数を実行できるかどうかを確認していってみてください。
それぞれの呼び出し規約の機能については下記のページに書かれています。
http://msdn.microsoft.com/ja-jp/library/46t77ak2.aspx
なお、上記に書いたとおり、関数の宣言に呼び出し規約が指定されていたら設定を変更しても意味が無いので、
先にヘッダの該当する関数宣言の確認してください。
int <u>DLLDECL</u> dllfunc();
のように、戻り値の型と関数名の間に単語が入っていたらそれが呼び出し規約の指定です。
殆どの場合、マクロを使って指定しているので、元をたどればどんな呼び出し規約を指定しているかは確認できます。
ちなみに、今回発生しているランタイムエラーは、
「ESPの値が正しく関数呼び出しの間で保存されませんでした。
これは、通常の関数呼び出しの結果は1つの関数ポインタで呼び出し規約を持つ別の呼び出し規約で宣言されたと宣言しました。」
(注:機械翻訳です)
となっています。
つまり、 ESP (スタックポインタ)が関数を呼び出した後、正しい位置に戻ってこなかったことを示しています。
Re:DLLファイルが読み込まれない?
Posted: 2009年11月24日(火) 22:54
by ジャーニー
できました!ありがとうございます
_stdcallにすれば動きました
ただ別の問題が発生しました
このDLLをもうひとつDXライブラリで作っているプログラムに入れるのですが、ためしにそっちで_stdcallになおしたときDXライブラリの関数が未解決の外部シンボルとなってしまいます
御津凪さんのいわれているマクロを使えば大丈夫なのでしょうが、リンク先を見てみたのですがいまいちよくわからなかったです
簡単な例などあれば教えていただきたいのですがよろしいでしょうか
Re:DLLファイルが読み込まれない?
Posted: 2009年11月24日(火) 23:11
by 御津凪
DXライブラリの関数宣言群には、先述した呼び出し規約を明示的に指定していないので、コンパイラ側で変更した呼び出し規約で外部参照(シンボル)名が一致しなくなったのが原因ですね。
(呼び出し規約ごとに外部参照名が変化するため)
問題の発生していた DLL のヘッダにのみ正しい呼び出し規約を指定する必要が出たので、ヘッダを修正する必要がありますね。
呼び出し規約は関数宣言の戻り値と関数名の間に記述するので、対象ヘッダ内のすべての関数宣言に呼び出し規約を入れる必要があります。
この場合はただ単に、
int _stdcall dllfunc();
を入れていってもいいのですが、
後でもし何か問題があって、呼び出し規約を変えたい時にすぐ対応できるように、
#define MY_DECL _stdcall
と対象ヘッダの先頭あたりに記述し、
後は _stdcall の代わりに指定したマクロ名を入れていけば大丈夫です。
(マクロ名はDLLの名前などにしておくといいかもしれません)
あと、コンパイラの設定を元の設定に戻しておくのを忘れないでください。
「<親またはプロジェクトの既定値から継承>」でデフォルトに戻せます。
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 00:05
by ジャーニー
詳しく回答していただきありがとうございます
ただ何度も申し訳ないのですが最初にアップロードしたhppファイルなのですが、ちょっと勉強不足でよくわからない方法で関数読み込みをしているため、そこでその方法を指定すればわからないのですがどのように指定すればいいのでしょうか
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 00:14
by ジャーニー
ってすいませんアップロードしわすれていたみたいです
大変申し訳ありません
ちゃんと見直せばよかったです
hppファイルだけですがこちらになります
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 00:17
by 御津凪
今回の場合であれば、 HAROC2D.hpp の中にある関数宣言文を対象に行えばいいのではないでしょうか。
恐らくそれだけで済むかと思います。
(HAROC2D.hpp の中に HAROC2 の他のヘッダをインクルードされていたらそれも対象に行ってください)
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 00:21
by 御津凪
添付していただいたヘッダの場合だと、
/* API関数型定義 */
の中の typedef 群ですね。
typedef int ( *THAROC_InitDriver )( int );
のような感じになっている所を、
typedef int (_stdcall *THAROC_InitDriver )( int );
のように入れていけばOKです。
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:02
by ジャーニー
今教えていただいた方法でやってみました
呼び出し規約を親またはプロジェクトから継承にし、
#define MY_DCEL _stdcall
・
・
・
typedef int (MY_DCEL *THAROC_InitDriver )( int );
のように変更してみたのですがESPがまた出てしまいました
プロジェクトファイルをあげようとしたのですがファイル制限をこえてしまったためソースのみあげさせていただきます
ただDLLファイルがどう圧縮しても120KB制限にひっかかったためアップロードできないみたいです
若干の改変(ヘッダファイルの移動くらいですが)を行ったものです
おそらく私が変なことをしただけだと思うのですが・・・
何度も質問してしまいお手数をおかけしますがよろしくお願いします
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:16
by 御津凪
コード自体にはそれらしいミスが無いので、実際に DLL を読み込んで試さないとわかりませんね…。
DLLを圧縮したものを下記のメルアドに送ってもらえませんか?
mitsunagistudio@gmail.com
(解決した後、受け取ったファイルは破棄いたします)
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:22
by ジャーニー
DLLファイルを送らせていただきました
お手数ですがよろしくお願いします
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:28
by 御津凪
さっそく受け取り、確認してみました。
結果はエラーが発生しませんでした。
(_stdcall を外して試すときちんとランタイムエラーが出ました)
エラーが出るということはきちんとビルドされていないのかもしれません。
リビルドして確かめてみましたか?
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:43
by ジャーニー
ソリューションのクリーンを行い、最初からビルドしてみましたが無理でした
エラーがでなかったということで、もう一度試してみたのですがやはりESPがでてしまいました
もしかするとプロジェクトの設定がまずかったのかもしれませんので、上記のアドレスにプロジェクトごと送らせていただいたので確認していただいてもよろしいでしょうか
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:47
by 御津凪
すいません。届いていないみたいです。
再度お願いできますか?
(圧縮したほうがいいです)
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:51
by ジャーニー
すいません途中でエラーがでてしまっていたみたいです
今送信完了しました
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 01:58
by 御津凪
エラーの原因を捕捉しました。
test.cpp では、
#include "../../../HAROCLIB/HAROC2D.hpp"
のファイルをインクルードしていますが、
変更を加えたヘッダファイルはこれではないので、エラーが出ます。
これを修正したヘッダファイルをインクルードするように直せばうまくいくはずです。
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 02:15
by ジャーニー
今確認したところ完全に間違えていましたorz
人間の思い込みって怖いですね
夜分遅くまでこのような質問にお答えいただいてありがとうございました
御津凪さんのサイトにもたくさんおもしろそうなものがありましたので参考にさせていただきます
ありがとうございました
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 02:20
by 御津凪
それでは解決したそうなので、メールにて受け取った各メール・ファイルは破棄しておきます。
あと、解決した場合は解決マークを付けてくださいね。(ニアミスでした)
Re:DLLファイルが読み込まれない?
Posted: 2009年11月25日(水) 02:20
by ジャーニー
解決にし忘れていました