C++ 快速回顧(五)
- 前言
- 一、Dll和Lib的區別
- 區別
- 在開發中使用
- 二、封裝并使用C++庫
- 1.封裝庫
- 2.使用庫
- 三、封裝并使用C庫
- 1.封裝庫
- 2.使用庫
前言
用于快速回顧之前遺漏或者補充C++知識
一、Dll和Lib的區別
靜態庫(LIB)在編譯時鏈接,代碼被復制到可執行文件中。
動態庫(DLL)在運行時鏈接,可執行文件只包含對 DLL 中函數的引用。
區別
文件分布??:
靜態庫:可執行文件獨立,不需要額外的庫文件。
動態庫:可執行文件需要依賴 DLL 文件。
??更新和維護??:
靜態庫:更新庫需要重新編譯程序。
動態庫:更新 DLL 可以獨立進行(但要保持接口兼容),程序無需重新編譯。
??內存占用??:
靜態庫:每個使用庫的程序都會在內存中有自己的一份庫代碼拷貝。
動態庫:多個程序可以共享內存中的同一份 DLL 代碼。
??加載??:
靜態庫:在程序啟動時,代碼已經被加載。
動態庫:可以在程序啟動時加載(隱式鏈接),也可以在程序運行時按需加載(顯式鏈接,使用 LoadLibrary 和 GetProcAddress 函數)。
在開發中使用
靜態庫(LIB)的使用??:
在項目配置中,需要指定靜態庫的路徑和庫文件名。鏈接時,鏈接器會將庫中的代碼直接整合到可執行文件中。
??動態庫(DLL)的使用??:
需要兩個文件:DLL 文件和導入庫(.lib)。在鏈接時,使用導入庫來解析符號,但代碼不會復制到可執行文件。運行時,DLL 文件必須放在可執行文件的目錄或系統路徑中。
如何選擇??:
如果需要減少可執行文件的大小,方便更新,或者多個程序共享庫代碼,則使用 DLL。
如果希望程序獨立運行,不依賴外部文件,則使用靜態庫。
二、封裝并使用C++庫
題外話:防止頭文件被重復包含的兩種方式
1.#pragma once
2.宏定義包裹,如下:
#ifndef INTERFACE_H
#define INTERFACE_H//TODO:#endif // !INTERFACE_H
1.封裝庫
定義導出宏
#define TESTCPP_API __declspec(dllexport)
整體的頭文件如下,IInterface這個類加了導出宏就可以被導出給外界使用
具體的實現如下,FHello這個類沒有加導出宏,我們只在內部使用導出后的DLL無法直接使用此類
如下代碼就是將FHello這個類作為內部實現,然后提供CreateInterface 這個接口給外界調用,返回的是內部定義的類
在項目屬性中分別選擇Dll和Lib導出
會生成以下這些文件
我們最后實際上使用的只有如下這幾個文件,頭文件是方便我們調用函數等查看使用,具體的實現都在dll或者lib中了
2.使用庫
有了上面導出的庫文件,我們可以來使用了
我們新建控制臺項目,導入之前生成的庫文件到自定義的目錄中
可以看到我們可以正常包含我們實現的內容
#include "dlllib/Interface.h"
#include <iostream>int main()
{IInterface* Interface = IInterface::CreateInterface();Interface->Init();printf(Interface->GetName());Interface->Destroy();system("pause");return 0;
}
但是這時候運行卻運行不起來
我們需要根據需要設置此路徑
此處有兩種方式可以選擇
第一種是直接在設置處設置即可
第二種是在代碼中設置
在生成前把庫拷貝到對應生成目錄之下
xcopy /e /r /y $(ProjectDir)dlllib $(OutDir)
三、封裝并使用C庫
1.封裝庫
使用c來封裝庫時要注意
#ifdef __cplusplus
extern "C"
{
#endif
同時注意函數要使用 ** __stdcall** 寫在要導出的函數前面,這個是函數壓棧依次進行的標識
下面是具體的函數實現
2.使用庫
使用的方式同上C++使用類庫
可以看到只有CTEST_API導出宏的函數可以正常進行使用,不然會在運行時報錯!!!