被同事問了一個使用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核心編程》。