文章目錄
- 一、創建動態庫dll (方法一)
- 1 生成C++ 動態庫dll
- 1.1 創建項目MyDLL
- 1.2 編寫.h 和 .cpp文件
- 1.3 設置 及 生成 DLL
- 2 調用 C++ 動態庫dll
- 2.1 創建C++ 空項目DLLtest
- 2.2 動態庫配置 及代碼調用測試
- 3 實際項目中的使用技巧
- 3.1 設置dll輸出路徑
- 3.2 設置頭文件引入路徑
- 3.3 改進后 測試
- 4 __cplusplus 解釋
- 5 完整代碼.h文件、.cpp 文件
- 6 完整項目文件下載
創建動態庫dll項目有兩種方法;
- 1.VS創建 C++ 空項目,然后在項目屬性中將項目
配置類型
改為動態庫(.dll)
,規范性要求不高,且創建方式熟悉。這種方法也可以用,但有時這種方法生成的dll在項目調用中, 會出現各種奇怪的錯誤。 故,此法 多用于新手測試,正式項目慎用。 - 2.VS創建 動態鏈接庫(DLL) 項目, 更安全、正規,代碼要求更規范。
一、創建動態庫dll (方法一)
1 生成C++ 動態庫dll
為了驗證效果,使用三種方法導出函數:
- //導出函數
- //導出類
- //以C方式導出函數
創建動態庫d11:1.VS創建動態鏈接庫(DLL) MyDLL:編寫.h和.cpp文件在.h文件中宏定義導出圖數2.生成dll文件:右鍵項目-->屬性-->配置類型-->動態庫( .dll)以Debug x64 生成解決方案
1.1 創建項目MyDLL
1.VS創建C++ 空項目MyDLL:
1.2 編寫.h 和 .cpp文件
添加 mathTest.h
和 mathTest.cpp
文件
mathTest.h
文件
#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定義導出:
#ifndef MATHTEST_ //如果沒有定義 MATHTEST_,就定義MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //導出
#else
#define MATHTEST_API __declspec(dllimport) //導入
#endif//導出函數
MATHTEST_API int add(int a, int b);//加法
MATHTEST_API int subtract(int a, int b);//減法//導出類
class MATHTEST_API mathTest
{public:int multiply(int a, int b);//乘法int divide(int a, int b);//除法
};//以C方式導出函數
//extern "C",告訴編譯器這里是C語言代碼//為了使自己建的庫可以在 C/C++ 通用調用,使用 __cplusplus ,
//當C++調用代碼時,__cplusplus 值為1,聲明函數外面就加了一層“extern "C" {}”;
//當C 調用代碼時,__cplusplus 值為0,就相當于沒有“extern "C" {}”;#ifdef __cplusplus
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b);//加法MATHTEST_API int Csubtract(int a, int b);//減法
#ifdef __cplusplus
}
#endif#endif
mathTest.cpp
文件
#include "mathTest.h"/*創建動態庫d11:1.VS創建C++ 空項目MyDLL:編寫.h和.cpp文件在.h文件中宏定義導出圖數2.生成dll文件:右鍵項目-->屬性-->配置類型-->動態庫( .dll)以Debug x64 生成解決方案
*///導出函數
int add(int a, int b)//加法
{return a + b;
}
int subtract(int a, int b)//減法
{return a - b;
}//導出類
int mathTest::multiply(int a, int b)//乘法
{return a * b;
}int mathTest::divide(int a, int b)//除法
{return a / b;
}//以C方式導出函數
int Cadd(int a, int b)//加法
{return a + b;
}int Csubtract(int a, int b)//減法
{return a - b;
}
1.3 設置 及 生成 DLL
右鍵項目–>屬性–>配置類型–>動態庫( .dll)
右鍵項目–>生成 (如修改后,可以點重新生成)
查看 生成的DLL文件
查看DLL
注意是.E:\Test\MyDLL\x64\Debug
,在工程同級目錄下\x64\Debug
下面
而不是 E:\Test\MyDLL\MyDLL\x64\Debug
,而不是在.h同級目錄的\x64\Debug
下面(剛開始就在這里找,發現MyDLL.dll.recipe
多了一個.recipe,迷糊了半天)
2 調用 C++ 動態庫dll
方法:
創建C++ 空項目DLLtest使用動態庫d11:隱式調用:1.把.lib(MyDLL.lib)、.dll(MyDLL.d11)、.h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.lib3.#include mathTest.h4.代碼調用
2.1 創建C++ 空項目DLLtest
這里測試代碼有兩種建里新項目的方法:
- 1可以直接在 "MyDLL”解決方案下 建創建C++ 空項目DLLtest;( 實際項目中dll項目和用戶項目建立在同一個解決方案下,這樣更方便代碼修改與管理,在調試時 主項目代碼還可以直接調試訪問dll中的源代碼,這樣就更方便dll代碼的調試優化等操作。)
- 2 也單獨建立一個項目方案;
這里為了方便,直接原來的解決方案上新增測試項目,這樣做的好處是
,如果測試之后dll代碼有問題或功能達不到預期,可以方便隨時修改dll的源代碼。
右鍵 解決方案"MyDLL”->添加->新建項目;創建C++ 空項目DLLtest
可以看到,解決方案下有兩個項目,“DLLtest
”和“MyDLL
”
在DLLtest項目下添加,main.cpp文件
2.2 動態庫配置 及代碼調用測試
使用動態庫d11:
隱式調用:
隱式調用:1.把.lib(MyDLL.lib)、.dll(MyDLL.dll)、.h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.lib3.#include mathTest.h4.代碼調用
在我們的dll文件中分別設置了 導出函數、導出類成員函數、以C方式導出的函數,現在這三種函數都在main文件中調用測試。
完整代碼
#include<iostream>
#include"mathTest.h"
using namespace std;/*
VS創建C++ 空項目DLLtest使用動態庫d11:隱式調用:1.把.lib(MyDLL.lib)、.d11(MyDLL.d11)、.h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.1b3.#include mathTest.h4.代碼調用
*/int main()
{//調用dll 導出函數int sum = add(10, 5);int sub = subtract(10, 5);//調用dll 導出類成員函數mathTest mathT; //實例化對象int mul = mathT.multiply(10, 5);int div = mathT.divide(10, 5);//調用dll 以C方式導出的函數int Csum = Cadd(10, 5);int Csub = Csubtract(10, 5);cout << "我的動態庫dll調用: "<< endl;cout << "add(10,5) = " << sum << endl<< "subtract(10,5) = " << sub << endl<< "multiply(10,5) = " << mul << endl<< "divide(10,5) = " << div << endl<< "Cadd(10,5) = " << Csum << endl<< "Csubtract(10,5) = " << Csub << endl;return 0;
}
運行測試,報錯。是因為 當前啟動項為“MyDLL
”,需要將啟動項設為 “DLLtest
”。
右鍵 “DLLtest
”,選擇“設為啟動項”
導出函數、導出類成員函數、以C方式導出的函數,現在這三種函數都用結果都輸出了,說明這三種dll導出函數方式都有,但我最常用的是 以C方式導出的函 ,這中通用個,避免出錯。
3 實際項目中的使用技巧
自動路徑(.dll、.lib、.h復制到 測試項目的.cpp目錄下,太麻煩)
3.1 設置dll輸出路徑
直接將dll生成文件,的生路徑設為 “DLLtest
”項目下的.cpp
路徑;
打開項目,觀察路徑位置關系
為了是的路徑通用,這里使用相對路徑 ../DLLtest/
,并且將 MyDLL設為啟動項,方便后面dll重新生成
重新生成dll,可見新的dll文件已經 生成在DLLtest項目下面了
3.2 設置頭文件引入路徑
將DLLtest設為啟動項;
設置DLLtest項目的 附加包含目錄為 …/MyDLL/這樣DLLtest項目就可以訪問 mathTest.h
文件了。
3.3 改進后 測試
注意:既然新的dll生成路徑已經更改到 “DLLtest
”項目下的.cpp
路徑,那么第一次在 MyDLL\x64\Debug\
路徑下生成的生成的dll
最好刪掉,
不然兩個路徑同時存在dll,調用時會產生混淆,當兩個路徑下的dll代碼源文件完全一樣時,似乎并沒有影響。一旦新的dll代碼修改了,這時兩個路徑下dll內容不一致,調用運行時就會出錯。
所以下面的4文件刪掉。
4 __cplusplus 解釋
為了使自己建的 C/C++ 庫可 都可以通用
使用 __cplusplus
,
- 當C++代碼時,
__cplusplus
值為1; - 當C 代碼時,
__cplusplus
值為0;
#ifdef __cplusplus
.
.
.
#endif
下面是完整的.h文件
//#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定義導出:
#ifndef MATHTEST_ //如果沒有定義 MATHTEST_,就定義MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //導出
#else
#define MATHTEST_API __declspec(dllimport) //導入
#endif//動態鏈接MATHTEST_API庫//以C語言的方式導出函數
//extern "C",告訴編譯器這里是C語言代碼#ifdef __cplusplus
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b); //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b); //除法#ifdef __cplusplus
}
#endif#endif
當C++ 代碼時,__cplusplus
值為1,那么源代碼對應部分 等價于
extern "C"
{MATHTEST_API int Cadd(int a, int b); //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b); //除法
}
#endif
當C 代碼時,__cplusplus
值為0,那么源代碼 對應部分 等價于;
(#ifdef __cplusplus
…#endif
部分是沒有執行的)
MATHTEST_API int Cadd(int a, int b); //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b); //除法
5 完整代碼.h文件、.cpp 文件
為了統一規范,同時使用“以C語言的方式導出函數”
mathTest.h文件
#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定義導出:
#ifndef MATHTEST_ //如果沒有定義 MATHTEST_,就定義MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //導出
#else
#define MATHTEST_API __declspec(dllimport) //導入
#endif//以C方式導出函數
//extern "C",告訴編譯器這里是C語言代碼//為了使自己建的庫可以在 C/C++ 通用調用,使用 __cplusplus ,
//當C++調用代碼時,__cplusplus 值為1,聲明函數外面就加了一層“extern "C" {}”;
//當C 調用代碼時,__cplusplus 值為0,就相當于沒有“extern "C" {}”;#ifdef __cplusplus
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b); //加法MATHTEST_API int Csubtract(int a, int b);//減法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b); //除法#ifdef __cplusplus
}
#endif#endif
mathTest.cpp文件
#include<iostream>
#include"mathTest.h"
using namespace std;/*
VS創建C++ 空項目DLLtest使用動態庫d11:隱式調用:1.把.lib(MyDLL.lib)、.d11(MyDLL.d11)、.h(mathTest.h)文件放到工程目錄下(DLLtest項目的.cpp同目錄下)2.項目右鍵-- > 屬性-->配置屬性-->鏈接器-->輸入->附加依項-- > 添加MyDLL.1b3.#include mathTest.h4.代碼調用
*/int main()
{//調用以C方式導出的函數int Csum = Cadd(10, 5);int Csub = Csubtract(10, 5);int Cmul = Cmultiply(10, 5);int Cdiv = Cdivide(10, 5);cout << "我的動態庫dll調用: " << endl;cout << "Cadd(10,5) = " << Csum << endl<< "Csubtract(10,5) = " << Csub << endl<< "Cmultiply(10,5) = " << Cmul << endl<< "Cdivide(10,5) = " << Cdiv << endl;return 0;
}
6 完整項目文件下載
完整項目工程文件,下載后可直接編譯運行
代碼下載:C++ 生成動態庫.dll 及 C++調用DLL