被同事问了一个使用dll导出函数导致编译不过的问题,写博客整理备忘。
假设我在做一个计算器,然后里头的数学运算希望放到一个dll中实现,方便复用。
计算器calc.exe
数学运算库:math.dll math.lib
我希望在math.dll中导出int add(int,int);函数给calc.exe使用
做法:
第一步:在math项目对应中添加两个文件
math.h
#ifdef MATH_LIB
#define MATHAPI extern "C" __declspec(dllexport)
#else
#define MATHAPI extern "C" __declspec(dllimport)
#endif
MATHAPI void add(int,int);
math.cpp
#include "math.h"
#define MATH_LIB
int add(int a, int b) { return a + b; }
第二步:在calc项目中添加main.cpp
#include "math.h"
#pragma comment(lib, "math.lib")
int main()
{
int sum = add(1, 2);
return 0;
}
说明:
1.math工程中我们定义了MATH_LIB宏,所以MATHAPI就被定义成了 extern "C" __declspec(dllexport)
也就是说函数使用这个修饰符就是说明是导出的函数,可以被外面使用。
2.calc工程中没有定义MATH_LIB宏,所以MATHAPI就被定义成了 extern "C" __declspec(dllimport)
也就是说add函数是别的dll中导出的,不是我自己实现的函数。
3.注意#pragma comment(lib, "math.lib")这个是让calc在链接阶段去math.lib中找函数符号。如果没有这句话会导致
链接的时候失败。如果有math.lib但是没有math.dll整个编译链接都不会有问题的,运行的时候才会提示math.dll找不多。
4.extern "C" 的使用是为了让C语言也能使用导出的函数,主要是为了避免编译器的名称改编行为。extern "C" 是在编写c++代码时需要用到的,编写c语言程序是不需要这个标记的。
总结:
无论是在微软代码里头还是谷歌代码里头,一般导出dll的函数都是这么使用的,也很简单。
不过里头还涉及很多关于dll的一些原理,这里暂时不写出来了,感兴趣的同学可以去看看《windows核心编程》。