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)
写在enum
、class
这些修饰后面就好。
导出代码
毕竟是插件,主程序是需要调用你的代码的,因而你需要声明你这些函数是可以调用的,不过这只是在代码里声明,不必在CMake中声明,因为这些方法都是你自己定义的,没必要告诉任何人是怎么完成的功能,只需要告诉他们可以调用就行。代码和导入代码类似:
1
2
3
4
5
extern "C" {
__declspec(dllexport) int load();
}
与导入代码唯一的区别就是前缀__declspec(dllimport)
改成了__declspec(dllexport)
,其他完全相同。如果你要导出类,也可以参考上文的主程序导出代码,在此不再赘述。
至此动态链接库dll
的内容就讲得差不多了,完成接口对接之后剩下的就是正常编程即可,但是考虑到也可能有跨语言的对接需求,所以本文接下来部分我希望以Java
对接C++
为例讲解一下。
跨语言对接
(学习中…)