如何从共享库调用函数? [英] How to call a function from a shared library?
问题描述
有人可以提供示例代码来显示如何使以下工作,用户将自己的版本 foo
编译到共享库中?
//函数原型,在运行时加载的实现:
std :: string foo(const std :: string);
int main(int argc,char ** argv){
LoadLibrary(argv [1]); //加载库实现foo
std :: cout<<< 结果:<< FOO( 测试);
return 0;
}
BTW,我知道如何编译共享库( foo.so
),我只需要知道一个简单的方式在运行时加载它。
p> 注意:您正在围绕库调用传递C ++对象(在这种情况下为STL字符串)。 没有标准的C ++ ABI 在这个级别,所以要么尝试避免传递C ++对象,或者确保您的库和程序都是使用相同的编译器构建的(理想情况下在同一台机器上是相同的编译器,以避免任何微妙的配置相关的惊喜。)
不要忘记声明导出的方法 externC
。
以上据说,这里是一些代码实现你想要实现的内容:
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
返回:: 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);
What is the easiest and safest way to call a function from a shared library / dll? I am mostly interested in doing this on linux, but it would be better if there were a platform-independent way.
Could someone provide example code to show how to make the following work, where the user has compiled his own version of foo
into a shared library?
// 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;
}
BTW, I know how to compile the shared lib (foo.so
), I just need to know an easy way to load it at runtime.
NOTE: You are passing C++ objects (in this case STL strings) around library calls. There is no standard C++ ABI at this level, so either try to avoid passing C++ objects around, or ensure that both your library and your program have been built with the same compiler (ideally the same compiler on the same machine, to avoid any subtle configuration-related surprises.)
Do not forget to declare your exported methods extern "C"
inside your library code.
The above having been said, here is some code implementing what you said you want to achieve:
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
You can abstract this further:
#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);
这篇关于如何从共享库调用函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!