@acidlemonについて
|'-')/ acidlemonです。鎌倉市在住で、鎌倉で働く普通のITエンジニアです。
30年弱住んだ北海道を離れ、鎌倉でまったりぽわぽわしています。
Windowsでダイナミックロードしたいときは何を使うー? そうです、DLL(Dynamic Link Library)です。
Linuxとか(POSIX系全般)でダイナミックロードしたいときは何を使うー? そうです、SOモジュール(Dynamic Shared Object)です。
そのぐらいの知識はあったし、DLLやSOモジュールを実行時リンクで読み込んだことやWindowsでDLLをLoadLibraryしたことはあったけどLinuxとかでSOモジュールを動的に読み込んだことがなかった。ので、やってみた。今日はそのメモ。
DLLになったりSOモジュールになったりするほうのcppファイル。
#include <stdio.h> #ifdef _WIN32 // Windows System needs DLL EntryPoint #include <windows.h> BOOL APIENTRY DllMain(HANDLE, DWORD, LPVOID){ return TRUE; } #endif extern "C"{ void testcall(){ printf("this is test call.\n"); } int testcall2(int val){ printf("this is test call 2, val=%d\n", val); return val+1; } }
DLLなりSOモジュールなりを動的にロードするほうのcppファイル。システムの違いを明確にするために、#ifdefで分けまくりです。
#include <stdio.h> #include <stdlib.h> #ifdef _WIN32 #include <windows.h> #else #include <dlfcn.h> #endif int main(int argc, char* argv[]){ void (*func1)(void); int (*func2)(int); #ifdef _WIN32 HMODULE handle; handle=LoadLibrary("plugin/testmod1.dll"); #else void* handle; handle=dlopen("plugin/testmod1.so", RTLD_LAZY); #endif if(!handle){ printf("cant open testmod1.so\n"); exit(1); } #ifdef _WIN32 *(void**)(&func1)=GetProcAddress(handle, "testcall"); *(void**)(&func2)=GetProcAddress(handle, "testcall2"); #else *(void**)(&func1)=dlsym(handle, "testcall"); *(void**)(&func2)=dlsym(handle, "testcall2"); #endif func1(); int retval=func2(3); printf("func2 returned %d\n", retval); #ifdef _WIN32 FreeLibrary(handle); #else dlclose(handle); #endif return 0; }
あと、WindowsでDLLつくるときはモジュール定義ファイルか__declspec(dllexport)が必要なので、今回は前者でエクスポートテーブルを定義。
LIBRARY testmod1 EXPORTS testcall @1 testcall2 @2
こいつをLinuxでコンパイルして実行するとー
[kawazoel@sekiya dsotest]$ g++ testmod1.cpp -g -shared -o plugin/testmod1.so [kawazoel@sekiya dsotest]$ g++ testloader.cpp -g -rdynamic -ldl -o test [kawazoel@sekiya dsotest]$ ./test this is test call. this is test call 2, val=3 func2 returned 4
Windows(Visual Studio 2005)でコンパイルして実行するとー
Z:\dsotest>cl testmod1.cpp /LD /link /DEF:testmod1.def /OUT:"plugin/testmod1.dll" Z:\dsotest>cl testloader.cpp /link /OUT:test.exe Z:\dsotest>test.exe this is test call. this is test call 2, val=3 func2 returned 4
とまぁこんな感じでどちらのプラットフォームでも同じようにダイナミックロードすることができましたー。あとはなんかこれをカプセル化するようなクラスをつくって、#ifdefをそこに押し込めば、プラットフォームを意識しないダイナミックロードができるようになりそうですねーみたいな話。
いや何の役に立つのかは知りませんが。