Win32/Linux 动态链接库加载类






3.94/5 (14投票s)
一个动态加载 DLL 和 SO 文件并从中调用函数的类

引言
这个类允许你加载一个库(一个 .dll 或 .so 文件)并从 Windows 或 Linux 上的库中获取函数地址。
背景
我一直在寻找一个像这样的简单类,用于我的一些跨平台程序,但没有找到,所以我自己创建了一个。
Using the Code
首先你需要知道的是(一件让我困扰了一段时间的事情),在 Linux 上你必须将 -ldl
添加到编译命令中,以便链接 dlopen
、dlsym
和 dlclose
。
解释代码的最佳方式是举一个例子...
#include <iostream>
using namespace std;
#include "BCLoadLib.h"
typedef int (*func)(int);
int main()
{
try{
BCLoadLib* dll = new BCLoadLib("lib");
cout << "Loaded.\n";
func f = (func)dll->getFunc("bob");
cout << f(7) << "\n";
delete dll;
cout << "Unloaded.\n";
}catch(char* e){
cout << e << "\n";
}
return 0;
}
第一行感兴趣的是
typedef int (*func)(int);
这是一个函数指针,你必须为想要从 DLL 中使用的每个函数自己定义这些。
库中这个函数的代码是,如果这不清楚,你应该查阅函数指针。
extern "C" __declspec(dllexport) int bob(int i){
return i;
}
你的函数必须是...
extern "C" __declspec(dllexport)
或
extern "C"
并且有一个 .def 文件。你不能使用这个库加载 C++ 函数。
这个类使用 throw
/catch
进行错误处理。如果它无法打开库(文件不存在或文件错误),或者如果它无法找到你使用 getFunc
请求的函数,它将抛出一个错误。
下一行重要的一行是我们在哪里创建类。
BCLoadLib* dll = new BCLoadLib("lib");
这实际上加载了库,Windows 支持直接发送名称,但在 Linux 上,我们必须添加 ./name.so,这样你的程序就不需要知道我们是在 Windows 还是 Linux 上。
接下来的两行重要的一行是获取函数地址并调用该函数
func f = (func)dll->getFunc("bob");
cout << f(7) << "\n";
请记住,func
是我们的 typedef
,用于该函数,所以我们创建一个新的 func f
并将地址设置为来自 DLL 的地址,将 void*
转换为我们的函数类型。
结论
好吧,我希望这对你们中的一些人有所帮助。请告诉我任何可能帮助或改进代码的事情(或者任何拼写错误 :P)。
历史
- 2006 年 10 月 12 日:修复了一些拼写错误。这段代码比较旧,我建议你查看这个类(它很小)并将其集成到你自己的代码中。
- 2006 年 4 月 17 日:修复了 Linux 加载代码中的内存泄漏和可能的内存访问错误。