如何从共享库调用函数? [英] How to call a function from a shared library?

查看:255
本文介绍了如何从共享库调用函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从共享库/ dll调用函数的最简单和最安全的方法是什么?我最感兴趣的是在linux上这样做,但如果有一个平台无关的方式会更好。

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.

有人可以提供示例代码来展示如何使下面的工作,用户已经将自己的 foo 版本编译到共享库中?

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;
}



我知道如何编译共享库( foo.so ),我只需要知道一个简单的方法来在运行时加载它。

BTW, I know how to compile the shared lib (foo.so), I just need to know an easy way to load it at runtime.

推荐答案

p> 注意:您正在传递C ++对象(在这种情况下是STL字符串)围绕库调用。 在此级别没有标准C ++ ABI ,因此请尽量避免传递C ++对象,或者确保您的库和您的程序都是使用相同的编译器构建的(理想情况下,在同一台机器上使用相同的编译器,以避免任何微妙的配置相关的惊喜。)

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.)

不要忘记声明导出的方法 extern

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

您可以进一步提取 p>

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆