C和C++中動態鏈接庫的創建和鏈接(原創,裝載請注明原處)

C和C++中動態鏈接庫的創建和鏈接

1.創建DLL(動態鏈接庫)-C++方式

1.創建DLL(動態鏈接庫-C++方式)

1.在VS(以VS2017為例)中創建DLL動態鏈接庫。


image

解決方案名稱為:MyDLL
項目名稱為:Dll1
2.創建頭文件Dll1.h
輸入如下代碼:

#pragma once
#ifdef MY_DLL_EXP
#else
#define MY_DLL_EXP _declspec(dllimport)////當編譯時,頭文件不參加編譯,所以.cpp文件中先定義,后頭文件被包含進來,因此外部使用時,為dllexport,而在內部編譯時,則為dllimport
#endif
//創建一個常量
MY_DLL_EXP extern const double PI;
//創建一個測試用的函數
void MY_DLL_EXP Hello();
//創建一個測試用的類
class MY_DLL_EXP Calculate {
public:
    double add(double a, double b);
    double sub(double a, double b);
    double mult(double a, double b);
    double divd(double a, double b);
};

3.創建Dll1.cpp(如存在則不用創建)
輸入如下代碼:

#include "stdafx.h"
#include "Dll1.h"
//注意以上兩個頭文件的相對順序不能改變
#include <iostream>
#define MY_DLL_EXP _declspec(dllexport)
//導出常量
const double PI = 3.14;
//導出函數
void  Hello() {
    std::cout << "Hello World!" << std::endl;
}
//導出類中的函數
double Calculate::add(double a, double b) {
    return a + b;
}
double Calculate::sub(double a, double b) {
    return a - b;
}
double Calculate::mult(double a, double b) {
    return a * b;
}
double Calculate::divd(double a, double b) {
    if (b == 0)
        return 0;
    return a / b;
}

4.生成即可完成C++版動態鏈接庫的創建
注意:動態鏈接庫文件不能直接執行

2.鏈接DLL(動態鏈接庫-C++方式)

1.隱式鏈接

1.準備
Dll1.h(Dll1項目目錄中)
Dll1.lib(解決方案的Debug中)
Dll1.dll(結局方案的Debug中)
2.創建一個測試用隱式鏈接動態鏈接庫的項目
此處以空項目為例


image

項目名稱為:testDll1
此處為了方便,將Dll1.h,Dll1.lib,Dll1.dll放入到新建的項目目錄下。
3.右擊解決方案,選擇屬性。在通用屬性中的啟動項目中選擇當前選中內容,確認即可。


image

4.右擊要鏈接DLL的項目testDll1,選擇屬性,進行配置。
(1)配置屬性->VC++目錄->在"包含目錄"里添加頭文件Dll1.h所在的目錄
image

image

image

(2)配置屬性->VC++目錄->在"庫目錄"里添加頭文件Dll1.lib所在的目錄
image

image

(3)配置屬性->鏈接器->輸入->在"附加依賴項"里添加Dll1.lib(若有多個lib則以空格隔開)


image

image

4.將Dll1.dll文件放入到創建的項目的目錄下或是解決方案的Debug目錄下
5.創建testDll1.cpp
輸入如下測試代碼:
#include "Dll1.h"
#include <iostream>
//隱式調用DLL
using namespace std;

int main() {
    cout << PI << endl;//測試輸出常量
    Hello();//測試函數
    //測試類
    Calculate calc;
    cout << "3 + 2 = " << calc.add(3, 2) << endl;
    cout << "4 - 1 = " << calc.sub(4, 1) << endl;
    cout << "3 * 2 = " << calc.mult(3, 2) << endl;
    cout << "4 / 2 = " << calc.divd(4, 2) << endl;
    cin.get();//暫停
}

輸出結果:


image

2.顯式鏈接

顯示鏈接可以在執行過程中隨時加載DLL文件,也可以隨時卸載DLL文件,這是隱式鏈接所無法作到的,所以顯式鏈接具有更好的靈活性,對于解釋性語言更為合適.
顯示鏈接主要是使用LoadLibrary()函數。此處只說明顯示鏈接DLL的導出函數的使用方法,導出類的使用比較復雜,將在我的其他文章中說明。
1.創建測試用空項目testDll2
2.將Dll1.dll放入到testDll2項目目錄下
3.創建testDll2.cpp
輸入如下代碼:

//顯示鏈接DLL-使用GetProcAddress獲取函數的名字會有所改變需要使用dumpbin.exe查詢
#include <Windows.h>//加載頭文件
#include <iostream>

using namespace std;
//設置全局變量hInst用于存儲dll句柄并加載動態鏈接庫
HINSTANCE hInst = nullptr;
//聲明函數指針
typedef void(*Hello)();

int main() {
    //加載動態鏈接庫D111.dll
    hInst = LoadLibrary("Dll1.dll");
    if (hInst == nullptr) {
        cout << "動態鏈接庫加載失敗!!!" << endl;
        FreeLibrary(hInst);
        cin.get();
        return 0;
    }
    //加載導出函數,此處函數名有所不同,需要使用dumpbin.exe進行查詢
    Hello hello = (Hello)GetProcAddress(hInst, "?Hello@@YAXXZ");
    cout << "Hello()=";
    hello();
    cin.get();
    //釋放動態鏈接庫
    FreeLibrary(hInst);
    return 0;
}

4.查詢函數名稱的方法
使用dumpbin.exe查詢
打開VS的自帶的本機工具命令提示
[圖片上傳失敗...(image-7efed-1547544495968)]
打開之后的界面:

image

進入Dll1.dll所在路徑
image

image

在控制臺中輸入dumpbin -exports Dll1.dll進行查詢
image

image

Hello函數的函數名為?Hello@@YAXXZ
5.生成并運行
運行結果
image

2.創建DLL(動態鏈接庫-C方式)

1.創建DLL(動態鏈接庫-C方式)

1.創建動態鏈接庫項目,名稱為Dll2
2.創建Dll2.h
輸入如下代碼

#pragma once
#ifdef MY_DLL_EXP
#else
#define MY_DLL_EXP _declspec(dllimport)////當編譯時,頭文件不參加編譯,所以.cpp文件中先定義,后頭文件被包含進來,因此外部使用時,為dllexport,而在內部編譯時,則為dllimport

#endif
//導出函數Add
extern "C" MY_DLL_EXP double Add(double a, double b);

3.創建Dll2.cpp(如果有則不需要創建)
輸入如下代碼:

#include "stdafx.h"
#include "Dll2.h"
//注意以上兩個頭文件的相對順序不能改變
#define MY_DLL_EXP _declspec(dllexport)

double Add(double a, double b) {
    return a + b;
}

4.生成即可。

2.鏈接DLL(動態鏈接庫-C方式)

1.隱式鏈接

1.準備
Dll2.dll(解決方案Debug目錄下)
Dll2.lib(解決方案Debug目錄下)
2.創建測試項目testDll3
3.把Dll2.dll和Dll2.lib放入到testDll3項目目錄下
4.創建testDll3.cpp
輸入如下代碼:

//隱式調用
#include <iostream>
#pragma comment(lib,"Dll2.lib")

using namespace std;
//載入函數,此處起到頭文件的作用
extern "C" _declspec(dllimport) double Add(double a, double b);

int main() {
    cout << "Add(3,4)=" << Add(3, 4) << endl;
    cin.get();
    return 0;
}

5.生成并運行
運行結果:


image

2.顯式鏈接

1.新建測試項目testDll4
2.把Dll2.dll放入新建的項目testDll4目錄中
3.新建testDll4.cpp
創建dll過程中使用C編譯器來編譯函數,這樣DLL文件中的函數名和原dll工程中的函數名就一致了。
墻裂推薦此種方式
輸入如下代碼:

//顯示鏈接DLL-C
#include <Windows.h>//加載頭文件
#include <iostream>

using namespace std;
//設置全局變量hInst用于存儲dll句柄并加載動態鏈接庫
HINSTANCE hInst = nullptr;
//聲明函數指針
typedef double(*Add)(double a,double b);

int main() {
    //加載Dll2.dll
    hInst = LoadLibrary("Dll2.dll");
    if (hInst == nullptr) {
        cout << "動態鏈接庫加載失敗!!!" << endl;
        FreeLibrary(hInst);
        cin.get();
        return 0;
    }
    //加載函數
    Add add = (Add)GetProcAddress(hInst, "Add");
    cout << "Add(3,4)="<<add(3,4)<<endl;
    cin.get();
    FreeLibrary(hInst);
    return 0;
}

4.生成并運行。

喜歡請關注一下呦~~~

簡書:http://www.lxweimin.com/u/27a54a63587e
博客園:https://www.cnblogs.com/xiangjinpeng/
CSDN:https://blog.csdn.net/qq_43210043
Github:https://github.com/XiangJinPeng

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容