文章

dll动态链接库的使用

动态链接库使用基础(基于我自己的摸索)

dll动态链接库的使用

B站视频推荐程序开发中,为了更具有可拓展性,我摸索学习了基于dll动态链接库的插件开发知识。并在本文记录关于如何使用dll库的知识

库开发

项目设置

为了使用dll库,我们必须首先开发一个dll库,因为不同语言的开发方法不尽相同,我主要是基于C++和Clion开发的,所以我也主要以C++为例说明。

为了编译出dll库,而不是一般编译结果的静态链接库.a,我们需要在CMake中添加设置,以我的ExamplePlugin为例:

1
2
3
add_library(ExamplePlugin SHARED main.cpp
        PluginInterface.h
)

add_library()中我们需要添加SHARED属性,否则构建之后会输出为.a的静态链接库。添加之后构建(build)我们的代码就可以在输出目录下找到.dll.dll.a文件,不过我们只需要.dll文件,至于另一个文件对我们没什么用了。至此,我们就可以正式进入代码开发部分了

导入代码

既然是开发插件,肯定避免不了需要引入主程序的代码,为此,我们需要先在CMake中添加一些设置:

1
2
target_link_libraries(ExamplePlugin PRIVATE BiliBili_Reranger)
# BiliBili_Reranger是我的主程序名

如果我们不添加这行设置,如果我们引入来自BiliBili_Reranger的代码,构建总会报错找不到方法,因为它并不知道你的这个方法是来自哪个程序嘛。

完成了CMake中关于环境的设置之后,我们还需要在代码中再声明一次,如下:

1
2
3
4
5
extern "C" {//这表示以C标准导出

__declspec(dllimport) int success();//引入的函数

}

其中extern "C"很重要,因为如果不加就会用C++的方式给你的函数修饰(比如将success函数改名为__success了),但是主程序没有修饰,还是叫success。那当你在环境中跑时就找不到__success函数,自然无法运行了(其实如果这样的话连构建都会失败)。随后你就可以在代码里随便使用success函数了。

至于success函数引入的写法,那倒没什么变化,只不过在前面加上__declspec(dllimport)罢了,其他没有什么影响。

如果你想要导入类,也是差不多的,比如假设主程序有导出类:

1
2
3
4
5
6
7
8
9
extern "C" {

enum PluginStatus {
    FAIL,
    SUCCESS,
    PASS
};

}

导入这个类:

1
2
3
4
5
6
7
8
9
extern "C" {

enum __declspec(dllimport) PluginStatus {
    FAIL,
    SUCCESS,
    PASS
};

}

只是注意__declspec(dllimport)写在enumclass这些修饰后面就好。

导出代码

毕竟是插件,主程序是需要调用你的代码的,因而你需要声明你这些函数是可以调用的,不过这只是在代码里声明,不必在CMake中声明,因为这些方法都是你自己定义的,没必要告诉任何人是怎么完成的功能,只需要告诉他们可以调用就行。代码和导入代码类似:

1
2
3
4
5
extern "C" {

__declspec(dllexport) int load();

}

与导入代码唯一的区别就是前缀__declspec(dllimport)改成了__declspec(dllexport),其他完全相同。如果你要导出类,也可以参考上文的主程序导出代码,在此不再赘述。

至此动态链接库dll的内容就讲得差不多了,完成接口对接之后剩下的就是正常编程即可,但是考虑到也可能有跨语言的对接需求,所以本文接下来部分我希望以Java对接C++为例讲解一下。

跨语言对接

(学习中…)

本文由作者按照 CC BY 4.0 进行授权