- ベストアンサー
bcc32 GetProcAddress( )
mydll.cpp と mymain.cpp でDLL内の関数を使うテストを しようとしたところです。 GetProcAddress( ) が失敗します。 どこを直せばいいか教えてください。 ///////// mydll.cpp #include <windows.h> extern "C" __declspec(dllexport) int MyFunc(int, int); int MyFunc(int a, int b){return( a + b );} ///////// mymain.cpp #include <windows.h> typedef int (*FUNCTYPE)(int, int); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ HMODULE hModule; FUNCTYPE ft; int i; switch(msg){ case WM_RBUTTONDOWN: hModule = LoadLibrary("mydll.dll"); ft = (FUNCTYPE)GetProcAddress(hModule, "MyFunc"); if(ft == NULL){ //GetLastError(); } i = (*ft)(7, 8); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int){ ・・・ } ///////// コンパイル C:\bcc32 -WD mydll C:\bcc32 -W mymain mydll.obj ///////// 実行 LoadLibrary( ) は NULL 以外を返しました。 DLL_PROCESS_ATTACH は確認できました。 GetProcAddress( ) は NULL を返しました。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
>アンダースコアが消えるという意味を教えてください。 デフォルトでは WINAPI を付けないと、関数 MyFunc のエクスポート名が "_MyFunc" になってしまうという意味です。 >プロシージャが見つからないと言うなんておかしなエラーだと思いました。 GetProcAddress は Get Procedure Address です。OS から見た場合、そのプログラムが C/C++言語で作られたかどうかは関係ないので、一般的にそう呼ばれていると思ってください。 あと、確認用に作ってみましたが、私の所では動いているようです。 ///////// mydll.cpp #include <windows.h> BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { return TRUE; } extern "C" int __declspec(dllexport) WINAPI MyFunc(int a, int b) { return a + b; } ///////// mymain.cpp #include <windows.h> typedef int WINAPI (*FUNCTYPE)(int, int); void mbox(LPCTSTR mess) { MessageBox(NULL, mess, "mymain", MB_OK); } int WINAPI WinMain(HINSTANCE i, HINSTANCE p, LPSTR c, int s) { HMODULE mydll = LoadLibrary("mydll.dll"); if (mydll) { mbox("mydll.dll のロードに成功した"); FUNCTYPE myfunc = (FUNCTYPE)GetProcAddress(mydll, "MyFunc"); if (myfunc) { mbox("MyFunc のアドレス取得に成功した"); char buff[256]; wsprintf(buff, "10 + 20 = %d", myfunc(10, 20)); mbox(buff); } else { mbox("MyFunc のアドレス取得に失敗した"); } FreeLibrary(mydll); } else { mbox("mydll.dll のロードに失敗した"); } return 0; }
その他の回答 (2)
WINAPI を付けるとエクスポート名の最初のアンダースコアが消えると思います。 extern "C" int WINAPI __declspec(dllexport) MyFunc(int, int); それで mymain 側にも WINAPI を付けてあげる。 typedef int WINAPI (*FUNCTYPE)(int, int);
お礼
ありがとうございます。 アンダースコアが消えるという意味を教えてください。 __declspec を _declspec にするということですか? _declspec もやってみたけど、結果は同じでした。 WINAPI を付けて、他の部分を少し直したけど、まだ GetProcAddress( ) == NULL で悩んでいます。 ///////// mydll.cpp #include <windows.h> extern "C" int WINAPI __declspec(dllexport) TestFunc(int, int); int WINAPI MyFunc(int a, int b){return( a + b );} ///////// mymain.cpp #include <windows.h> typedef int (*FUNCTYPE)(int, int); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ static HMODULE hModule; FUNCTYPE ft; int i; switch(msg){ case WM_RBUTTONDOWN: hModule = LoadLibrary("mydll.dll"); ft = (FUNCTYPE)GetProcAddress(hModule, "MyFunc"); if(ft == NULL){ char e[50]; wsprintf(e, "%lu", GetLastError()); MessageBox(hWnd, e, "GetProcAddress失敗", MB_OK); } i = (*ft)(7, 8); break; case WM_DESTROY: FreeLibrary(hModule); PostQuitMessage(0); break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int){ ・・・ } ///////// コンパイル C:\bcc32 -WD mydll C:\bcc32 -W mymain ///////// 実行 LoadLibrary( ) は NULL 以外を返しました。 DLL_PROCESS_ATTACH は確認できました。 GetProcAddress( ) は NULL を返しました。 GetLastError( ) は 127 で、指定されたプロシージャが見つからなかった という意味らしいです。それは mydll.dll から TestFunc が 見つからなかったということかな? TestFunc はプロシージャではなくて関数だと思うんだけど、 プロシージャが見つからないと言うなんておかしなエラーだと思いました。
- a-kuma
- ベストアンサー率50% (1122/2211)
よくは分からないんですが、 ・せっかく書いているのですから GetLastError() を調べましょう ・動的にロードするのに、コンパイルで mydll.obj があるのは不自然 といったあたりが怪しげ
お礼
ごめんなさい。エラーナンバーを書き忘れていました。 GetLastError( ) は 6 を返します。 6 はハンドルが無効という意味らしいです。 C:\bcc32 -W mymain mydll.obj を C:\bcc32 -W mymain にしてコンパイルしたけど、結果は同じでした。
お礼
ありがとうございます。 アンダースコアが付くというのは、目に見えないけど WINAPI を付けないと内部的に _MyFunc になってしまっていたんですね。 プロシージャが見つからないと言われたのもinthefloiさんの説明で 分かりました。 動作確認ありがとうございます。 残った問題は BCC32 でのDLL関係のリンクのソースと コンパイルスイッチだと思います。
補足
できました。 少しずつソースを変えて実験していたら、いつのまにか できるようになりました。下に書いたソースでもできました。 どこかでくだらないミスをしていたんだと思います。 DLL内の関数を使う部分は (*ft)(7, 8) を ft(7, 8) と 書いてもいいんですね。 ありがとうございました。