65.9K
CodeProject 正在变化。 阅读更多。
Home

Win32/Linux 动态链接库加载类

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.94/5 (14投票s)

2006 年 4 月 17 日

CPOL

2分钟阅读

viewsIcon

82596

downloadIcon

813

一个动态加载 DLL 和 SO 文件并从中调用函数的类

Sample Image - BCLoadLib.jpg

引言

这个类允许你加载一个库(一个 .dll .so 文件)并从 Windows 或 Linux 上的库中获取函数地址。

背景

我一直在寻找一个像这样的简单类,用于我的一些跨平台程序,但没有找到,所以我自己创建了一个。

Using the Code

首先你需要知道的是(一件让我困扰了一段时间的事情),在 Linux 上你必须将 -ldl 添加到编译命令中,以便链接 dlopendlsym 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 加载代码中的内存泄漏和可能的内存访问错误。
© . All rights reserved.