使用动态链接加载器 <dlfcn.h> 而不是直接函数调用的目的?

Purpose of using dynamic linking loader <dlfcn.h> instead of direct function call?

我今天遇到了类似这段代码的东西。

A.h中:

class A { blah blah blah }

#define CREATE_A_FUNC_NAME   ("CreateA")
extern "C" A* CreateA(void);
typedef A* (*funcCreateA)(void);

main.cpp中:

void* handle = dlopen("libA.so", RTLD_LAZY);
funcCreateA func = (funcCreateA)dlsym(handle, CREATE_A_FUNC_NAME);
A* a = func();

现在显然 A.h 只是声明的 header,它的所有实现都存储在 libA.so.

我已经测试过,如果我正确设置了我的项目,这意味着 lib 已正确链接,我可以简单地执行 A* a = CreateA() 来获取指向新创建的 A 实例的指针。因此问题来了。为什么要经历如此多的麻烦来实现像一个函数调用这样简单的事情?这种技术或技巧叫什么?优缺点都有什么?我什么时候应该使用这种技术?谢谢!

使用 dlsym 而不是直接 linking 到 DSO 的主要原因:

  • 您想为您的应用提供插件机制,因此您需要能够动态加载 DSO (linker 不知道插件你构建了 exe)。最简单的方法是添加一些虚拟基础 class (我假设 'A' 有一些虚拟方法?),然后导出一个创建者方法"C" linkage (禁用 C++ 名称修改)。看起来好像这是这里的意图?
  • 您可能针对特定 CPU 指令集优化了代码 (即在游戏引擎启动时,检查哪个是 CPU 支持的最新指令集,加载在运行时调用相关的 SSE 或 AVX 库,然后调用针对该特定 CPU) 优化的方法。
  • 在极少数情况下,您可能希望 'unload' 一些繁重的代码以释放设备上的更多内存。这种情况在 Android/iOS 和控制台 上经常发生(例如,在编译所有着色器后释放着色器编译器)

值得注意的是,如果您直接 link 到 DSO,在后台,linker 将在应用程序启动时简单地插入 dlsym/dlopen 代码,这将自动加载DSO 并解析符号。