从共享库/dll 调用函数最简单、最安全的方法是什么?我最感兴趣的是在 linux 上做这件事,但如果有一种独立于平台的方式会更好。
有人可以提供示例代码来展示如何进行以下工作,其中用户已将自己的 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
),我只需要知道一种在运行时加载它的简单方法。
最佳答案
注意:您正在围绕库调用传递 C++ 对象(在本例中为 STL 字符串)。 没有标准 C++ ABI在这个级别,所以要么尽量避免传递 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);
关于c++ - 如何从共享库中调用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2538103/