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

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

问题描述

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



有人可以提供示例代码来显示如何使以下工作,用户将自己的版本 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屋!

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