文章目錄
-
-
- 說明
- 動态庫和靜态庫聯系與差別
- 靜态庫(static lib)注意事項
- 動态庫(dynamic lib + dll)注意事項
- 常見問題
- 聯系部落客
-
說明
- 本文是在綜合CSDN部落格的基礎上,再加上部落客自己實踐總結所寫
- 部落客之前曾寫過一篇博文介紹該内容,但那篇文章有囫囵吞棗之意,是以“再談”
- 本文若有錯誤之處,請在評論留言,及時回複
- 本文涉及到的環境均為 Windows 10 + VS 2013
動态庫和靜态庫聯系與差別
- 這是部落客之前寫的一篇入門文章,可以結合的看
VS下靜态庫與動态庫的生成與使用
- 其它相關文章,部落客推薦
static lib和dynamic lib
VS2013動态庫檔案的建立及其使用詳解
c++導出庫
靜态庫(static lib)注意事項
- 建立靜态庫工程
- 正常寫 .h 和 .cpp
- 建立測試工程
- 編輯 test.cpp
- 将 .lib 複制到 test.cpp
- 【屬性 - 連結器 - 附加依賴項】加入 .lib 名稱
- 編譯運作
動态庫(dynamic lib + dll)注意事項
- 建立動态庫生成工程 DLLGenerater
- 選擇 控制台應用程式,其它請讀者自行嘗試,大同小異
- 選擇 DLL
- 勾選 空項目
- 預編譯頭VS 預設強制勾選
- 安全開發生命周期(SDL)檢查 選不選擇無所謂
- 建立若幹 .h 和 .cpp,每個 .h 又可包括若幹内容
- math.h 和 math.cpp 示例代碼(見文末所附代碼)
- animal.h 和 animal.cpp 示例代碼(見文末所附代碼)
- 不寫 main 函數
- 如果想驗證代碼的正确性,可在屬性将預設類型的配置類型像彗星修改為**.exe**進行編譯運作
- 編譯即可,在 …/Debug 或者 …/Release 目錄下生成 DLLGenerater.lib 和 DLLGenerater.dll
- 建立測試動态庫工程 DLLUser
- 建立 test.cpp
- 複制 math.h 和 animal.h 到 test.cpp 同一級目錄
- 複制 DLLGenerater.lib 和 DLLGenerater.dll 也到 test.cpp 同一級目錄
- DLLUser 屬性的連結器的附加依賴項中添加 DLLGenerater.lib
- 編輯 test.cpp 的内容(見文末所附代碼)
- 編譯運作成功
- 附:使用 DLLGenerater.dll 的幾種方式
- 編譯運作時候
- 第一種方式
- .h、.lib、.dll、随 test.cpp 同一級目錄
- 第二種方式
- .h、.lib 随 test.cpp 同一級目錄
- 系統環境變量的 system 的 path 加入 .dll 的路徑(Windows 下可能需要重新開機電腦)
- 第三種方式
- .h 随 test.cpp 同一級目錄
- test.cpp 中加入
#pragma comment(lib,"DLLGenerater.lib")
- 系統環境變量的 system 的 path 加入 .dll 的路徑(Windows 下可能需要重新開機電腦)
- 第四種方式(類似于配置第三方庫)
- 【項目屬性 - VC++目錄 - 包含路徑】 添加 .h 路徑
- 【項目屬性 - VC++目錄 - 包含庫目錄】 添加 .lib 路徑
- 【項目屬性 - 連結器 - 附加依賴項】 寫入具體的 .lib 名稱
- 系統環境變量的 system 的 path 加入 .dll 的路徑(Windows 下可能需要重新開機電腦)
- 第一種方式
- 脫離VS運作時候
- 第一種方式
- 将 .dll 和 .exe 放在一起
- 第二種方式(這個是我猜測的,未經實際驗證)
- 預先就在檔案中寫入 .dll 的相對路徑,這樣的話可以在程式打包釋出時候将 .dll 放入指定檔案夾,具體可參見現有軟體的安裝程式(如參看 QQ 的安裝程式路徑)
- 第一種方式
- 編譯運作時候
- 附:上述所提及代碼
math.h
#ifndef _MATH_H_
#define _MATH_H_
#include <cmath> // 記得加頭檔案
// 有時候覺得寫得麻煩
// 那麼可以 typadef
#ifndef MY_DLL // 條件編譯
#define MATH_EXPORT __declspec(dllexport)
#endif
// 對于函數(全局函數,成員函數等)
// __declspec(dllexport) 寫在最前面
// 然後是傳回值,函數名,形參
__declspec(dllexport) int add(int a, int b);
// 對于類,如果要導出所有函數
// 那麼 __declspec(dllexport) 寫在 class 和 類名中間
class __declspec(dllexport) ExportAllDll {
public:
float getSin(float theta); // 普通成員函數
static void printClass(); // 靜态函數
private:
const double PI = std::acos(-1);
// 私有函數,不會導出!!!并且該導出無實際意義
float __getTan(float theta);
};
// 對于類,如果要導出部分函數
// 則類名前不加 __declspec(dllexport)
// 而是在要導出的函數前面加上 __declspec(dllexport)
class ExportPartDll {
public:
__declspec(dllexport) float getSqrt(float num); // 導出
float getAbs(float num); // 不導出
};
// 也可以這樣導出函數
MATH_EXPORT void getMatrix();
#endif // _MATH_H_
math.cpp
#include "math.h"
#include <iostream>
// .cpp 實作檔案一概不寫 __declspec(dllexport)
int add(int a, int b){
return a + b;
}
// 類函數的實作記得加上類名
float ExportAllDll::getSin(float theta){
return std::sinf(theta * PI / 180);
}
// 這裡不寫 static
void ExportAllDll::printClass(){
std::cout << "printClass\n";
}
// 私有函數的實作
float __getTan(float theta){
return 90.0f;
}
// 這個是要導出的函數
float ExportPartDll::getSqrt(float num){
return std::sqrt(num);
}
// 這個不導出
float ExportPartDll::getAbs(float num){
return std::abs(num);
}
// typedef __declspec(dllexport) MY_DLL 的使用
void getMatrix(){
std::cout << "This is matrix.\n";
}
animal.h
#ifndef _ANIMAL_H_
#define _ANIMAL_H_
__declspec(dllexport) void printZoo();
#endif // _ANIMAL_H_
main.cpp
#include "animal.h"
#include <iostream>
void printZoo(){
std::cout << "printZoo()\n";
}
test.cpp
#include "math.h"
#include "animal.h"
#include <iostream>
int main(){
// 測試全局函數
int a = 1, b = 2;
std::cout << add(a, b) << std::endl;
// 測試導出類
ExportAllDll ad;
std::cout << ad.getSin(30) <<std::endl;
ExportAllDll::printClass();
// 測試類導出函數
ExportPartDll pd;
std::cout << pd.getSqrt(9.0f) << std::endl;
// std::cout << pd.getAbs(-6.6f) << std::endl;
// 測試全局函數
getMatrix();
// 測試全局函數
printZoo();
return 0;
}
常見問題
C++ dll庫隻生成dll檔案,而未生成lib檔案的問題
Error LNK2001 無法解析的外部符号 的幾種情況及解決辦法
聯系部落客
評論會盡快回複