Fra*_*ank 15 c++ linux dll shared-libraries dynamic-linking
从共享库/ 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;
}
顺便说一下,我知道如何编译共享的lib(foo.so),我只需要知道在运行时加载它的简单方法.
vla*_*adr 26
注意:您正在围绕库调用传递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);