こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

DLLの明示的な読み込みの方法

開発環境:WindowsXP sp2 + VisualStudio2005

MSDNやその他のWebページで、DLLの明示的なロードについて勉強しています。
試しに以下のようなコードを書いてみたのですが、コンパイルは通りますが、実行時にDLLが読み込まれているのにもかかわらず、関数のアドレスが取得できません。

---DLLのコード---
#include <iostream>
using namespace std;

__declspec(dllexport) void printMessage()
{
cout<<"printMessage関数が呼ばれた"<<endl;
}
---終わり---
コンパイルしたDLLのみをDLLを使用した実行形式がコンパイル後に収納されるフォルダに移動して、以下のコードを書いてコンパイルしました。
---EXEのコード---
#include <windows.h>
#include <iostream>

typedef void(*TFUNC)();

int main(void)
{
HINSTANCE hInstDLL;
TFUNC DllFunction;

//DLLの読み込み
hInstDLL=LoadLibrary(L"dll.dll");
if(hInstDLL==NULL)
{
std::cout<<"ERROR"<<std::endl;
return 0;
}

//printMessage関数のアドレスを取得
DllFunction=(TFUNC)GetProcAddress(hInstDLL,"printMessage"); //この辺りがおかしいかも知れない

//関数の使用
if(DllFunction==NULL)
{
std::cout<<"ERROR"<<std::endl;
FreeLibrary(hInstDLL);
return 0;
}
DllFunction();

//DLLの解放
if(!FreeLibrary(hInstDLL)) return 0;

return 0;
}
---終わり---

DLLは見つかる物の、どうも上手くいかないようです......原因は何なのでしょうか。

投稿日時 - 2007-05-16 23:14:42

QNo.3006164

困ってます

質問者が選んだベストアンサー

C++では関数名はvoid printMessage()と定義したつもりでも、
様々なsufixが付与され関数名が変わります。
例えば printMessage@XYZ_sufix などのように
同名の関数でも引数が違えば定義できるC++の仕様です。

そのため、Exportしている関数名も変わっているものと
思われます。
既に回答で出ていますが、DEFファイルを使ったExport
またはextern "C"リンゲージを使用する、
または正式な関数名を調べてそれを使用して
GetProcAddressを呼び出す必要があります。

投稿日時 - 2007-05-17 13:42:49

お礼

No.1の方へのお礼でも書いていますが、Depends.exeに入れたところ、たしかにprintMessage関数の名前が変わっていました(名前が追加された感じ?)
私がDLLを作って、他の方がDLL使うプログラムを開発する際に、suffix付きの名前を書かせるのはちょっと鬼かしらん......
defかextern"C"を使って名前をある程度固定してあげた方がやりやすそうですね。

的確な回答ありがとう御座いましたm(__)m

投稿日時 - 2007-05-19 14:02:39

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

★DllMain() はどうなっていますか?
・DLL のソースに DllMain() も記述しておきましょう。
・下にその参考になるリンクを貼っておきます。

参考文献:
http://www.geocities.jp/ky_webid/win32c/057.html→『第57章 ダイナミックリンクライブラリ(DLL)』
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpdllpro/html/_win32_DllMain.asp→『DllMain』
http://www.kumei.ne.jp/c_lang/sdk2/sdk_119.htm→『第119章 簡単なdllを作る』
http://www.kumei.ne.jp/c_lang/sdk2/sdk_122.htm→『第122章 dllを明示的に呼び出す』

参考URL:http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpdllpro/html/_win32_DllMain.asp

投稿日時 - 2007-05-18 21:04:41

お礼

DllMain関数はやはり自分で書かないといけませんか?
プロセスやスレッドの初期化時と終了時、また、LoadLibrary 関数と FreeLibrary 関数の呼び出し時に呼びだされるようですね......
自分で書きます、はい。

参考になるリンクも張っていただきありがとう御座いましたm(__)m

投稿日時 - 2007-05-19 14:04:47

ANo.3

FAY

> typedef void(*TFUNC)();
typedef __declspec(dllimport) void(*TFUNC)();
とか?

投稿日時 - 2007-05-17 09:18:31

お礼

書き直してみましたけど、上手くいかなかったような.......

結果は何にしろ、参考意見本当に感謝しておりますm(__)m

投稿日時 - 2007-05-19 13:57:43

ANo.2

C++のようなので、まずは
extern "C"
を使うべきでしょう。

そして、明示的に呼ぶなら定義ファイル(*.def)の設定も。

調べてみてください。

投稿日時 - 2007-05-17 01:13:49

お礼

おお、上手くいった......
やはりdefファイルがないと手間が掛かってしまいますね......

回答ありがとう御座いましたm(__)m

投稿日時 - 2007-05-19 13:55:27

ANo.1

Wr5

そのDLLをDepends.Exeに入れてみてください。
エクスポートされている関数の名前が、"printMessage"とは違っているかと思います。
DEFファイルを作成して、名前を固定するようにしたほうがいいでしょう。

参考URL:http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200602/06020009.txt

投稿日時 - 2007-05-17 01:12:17

お礼

Depends.exeに入れてみたところ、確かに私が打ち込んだ名前とは違っていました。
.....だから管理できるのか......

で、実際にEXEファイルのDLLの関数を読み出す部分にprintMessageの本来の名前を入力してみたところ、しっかりコンパイルが通り期待通りの実行結果が得られました。
DEFファイルで名前を固定する方法は参考になりました。

本当にありがとう御座いますm(__)m

投稿日時 - 2007-05-19 13:49:47

あなたにオススメの質問