从共享库/ dll调用函数的最简单,最安全的方法是什么?我对在Linux上执行此操作最感兴趣,但是如果有一种与平台无关的方法会更好。
有人可以提供示例代码来显示如何在用户将自己的版本编译foo到共享库的情况下执行以下工作吗?
foo
// function prototype, implementation loaded at runtime: std::string foo(const std::string); int main(int argc, char** argv) { LoadLibrary(argv[1]); // loads library implementing foo std::cout << "Result: " << foo("test"); return 0; }
顺便说一句,我知道如何编译共享库(foo.so),我只需要知道一种在运行时加载它的简单方法。
foo.so
注意: 您正在库调用周围传递C 对象(在这种情况下为STL字符串)。有 **没有标准的C ABI在这个水平**,所以无论是尽量避免将C ++对象周围,或确保两个资料库和程序已建成具有相同的编译器(最好在同一台机器上相同的编译器,以避免任何微妙与配置相关的惊喜。)
不要忘记在库代码中 声明导出的方法extern "C"。
extern "C"
上面已经说过了,这是 一些代码,实现您要实现的目标 :
typedef std::string (*foo_t)(const std::string); foo_t foo = NULL; ... # ifdef _WIN32 HMODULE hDLL = ::LoadLibrary(szMyLib); if (!hDll) { /*error*/ } foo = (foo_t)::GetProcAddress(hDLL, "foo"); # else void *pLib = ::dlopen(szMyLib, RTLD_LAZY); if (!pLib) { /*error*/ } foo = (foo_t)::dlsym(pLib, "foo"); # endif if (!foo) { /*error*/ } ... foo("bar"); ... # ifdef _WIN32 ::FreeLibrary(hDLL); # else ::dlclose(pLib); # endif
您可以 进一步抽象 :
#ifdef _WIN32 #include <windows.h> typedef HANDLE my_lib_t; #else #include <dlfcn.h> typedef void* my_lib_t; #endif my_lib_t MyLoadLib(const char* szMyLib) { # ifdef _WIN32 return ::LoadLibraryA(szMyLib); # else //_WIN32 return ::dlopen(szMyLib, RTLD_LAZY); # endif //_WIN32 } void MyUnloadLib(my_lib_t hMyLib) { # ifdef _WIN32 return ::FreeLibrary(hMyLib); # else //_WIN32 return ::dlclose(hMyLib); # endif //_WIN32 } void* MyLoadProc(my_lib_t hMyLib, const char* szMyProc) { # ifdef _WIN32 return ::GetProcAddress(hMyLib, szMyProc); # else //_WIN32 return ::dlsym(hMyLib, szMyProc); # endif //_WIN32 } typedef std::string (*foo_t)(const std::string); typedef int (*bar_t)(int); my_lib_t hMyLib = NULL; foo_t foo = NULL; bar_t bar = NULL; ... if (!(hMyLib = ::MyLoadLib(szMyLib)) { /*error*/ } if (!(foo = (foo_t)::MyLoadProc(hMyLib, "foo")) { /*error*/ } if (!(bar = (bar_t)::MyLoadProc(hMyLib, "bar")) { /*error*/ } ... foo("bar"); bar(7); ... ::MyUnloadLib(hMyLib);