C++中dlsym()和dlopen()的替代品

sud*_*03r 18 c++ shared-libraries dynamic-loading dlsym

我有一个应用程序,其中一部分使用共享库.这些库在编译时链接.
在运行时,加载器期望共享对象在LD_LIBRARY_PATH,如果没有找到整个应用程序崩溃,错误"无法加载共享库".注意,不能保证客户端将拥有库,在这种情况下我想要应用程序留下合适的错误消息,独立部分也应该正常工作.

为此,我使用dlsym()dlopen()在共享库中使用API​​.这个问题是如果我在API中有很多功能,我必须单独使用dlsym()和ptrs 访问它们,在我的情况下会导致内存损坏和代码崩溃.

这有什么替代方案吗?

Emp*_*ian 32

你的问题的常见解决方案是声明一个函数指针表,做一个dlsym()来找到它,然后通过指向该表的指针调用所有其他函数.示例(未经测试):

// libfoo.h
struct APIs {
   void  (*api1)(void);
   void *(*api2)(int);
   long  (*api3)(int, void *);
};

// libfoo.cc
void fn1(void) { ... }
void *fn2(int) { ... }
long fn3(int, void *) { ... }

APIs api_table = { fn1, fn2, fn3 };


// client.cc
#include "libfoo.h"
...
  void *foo_handle = dlopen("libfoo.so", RTLD_LAZY);
  if (!foo_handle) {
     return false;            // library not present
  }
  APIs *table = dlsym(foo_handle, "api_table");
  table->api1();              // calls fn1
  void *p = table->api2(42);  // calls fn2
  long x = table->api3(1, p); // calls fn3
Run Code Online (Sandbox Code Playgroud)

PS使用dlsym和指针单独访问API函数本身并不会导致内存损坏和崩溃.很可能你只是有虫子.

编辑:
您可以使用与第三方库完全相同的技术.创建一个libdrmaa_wrapper.so并放入api_table其中.直接链接包装器libdrmaa.so.

在主可执行文件中dlopen("libdrmaa_wrapper.so", RTLD_NOW).dlopen如果(并且仅当)libdrmaa.so在运行时出现并且提供您在中使用的所有API函数,这将成功api_table.如果成功,单个dlsym调用将允许您访问整个API.