天天看點

c++中.dll與.lib檔案的生成與使用的詳解

兩種庫:

•  包含了函數所在的DLL檔案和檔案中函數位置的資訊(入口),代碼由運作時加載在程序空間中的DLL提供,稱為動态連結庫dynamic link library。

•  包含函數代碼本身,在編譯時直接将代碼加入程式當中,稱為靜态連結庫static link library。

共有兩種連結方式:

•  動态連結使用動态連結庫,允許可執行子產品(.dll檔案或.exe檔案)僅包含在運作時定位DLL函數的可執行代碼所需的資訊。

•  靜态連結使用靜态連結庫,連結器從靜态連結庫LIB擷取所有被引用函數,并将庫同代碼一起放到可執行檔案中。

兩種檔案的差別

使用lib需注意兩個檔案:

•.h頭檔案,包含lib中說明輸出的類或符号原型或資料結構。應用程式調用lib時,需要将該檔案包含入應用程式的源檔案中。

•.LIB檔案。

使用dll需注意三個檔案:

•.h頭檔案,包含dll中說明輸出的類或符号原型或資料結構的.h檔案。應用程式調用dll時,需要将該檔案包含入應用程式的源檔案中。

•.LIB檔案,是dll在編譯、連結成功之後生成的檔案,作用是當其他應用程式調用dll時,需要将該檔案引入應用程式,否則産生錯誤(如果不想用lib檔案或者沒有lib檔案,可以用WIN32 API函數LoadLibrary、GetProcAddress裝載)。

•dll檔案,真正的可執行檔案,開發成功後的應用程式在釋出時,隻需要有.exe檔案和.dll檔案,并不需要.lib檔案和.h頭檔案。

1.生成lib檔案

  首先,我們先建立一個控制台工程(建立->工程->控制台程式),添加sub.cpp以及sub.h檔案。

//sub.h
#ifndef _SUB_H
#define _SUB_H
void sub(int a,int b);
#endif
//sub.cpp
#include "sub.h"
#include <iostream>
void sub(int a,int b)
{
    std::cout<<(a-b)<<std::endl;
}      

由于在工程中,沒有main()函數,是以直接編譯出錯。這時,要右鍵點選工程,并選擇工程屬性,出現下圖,選擇靜态連結庫即可。

c++中.dll與.lib檔案的生成與使用的詳解

這時候再按F7,build solution即可産生lib檔案。在Debug中隻生成.lib檔案。

2.生成dll檔案

  生成dll檔案的過程與上面的過程是一樣的,隻是在選擇Dynamic Library(.dll)即可。在Debug中會生成一個.lib和.dll兩種檔案。

c++中.dll與.lib檔案的生成與使用的詳解

3.兩種檔案的使用

  在使用時,靜态連結庫隻要把.h和.lib檔案加入到工程檔案夾中即可。而動态連結庫要把.h、.lib和.dll檔案加入到工程中。

#include <iostream>
#include "sub.h"  //連結庫的頭檔案
using namespaces std;
#pragma comment(lib,"sub.lib") //加傳入連結接庫
int main()
{
    sub(5,4);
    return 0;
}      

把.h和.lib的檔案放在相應的目錄下 ,有時候有錯誤,但是也能運作成功。

感覺靠譜的方法是像一些标準庫的方法,添加包含目錄和庫目錄,添加依賴項。

第一種方法:

把這個庫拷貝到工程目錄下,(最好拷貝到vs編譯器可以找到的目錄下,這個路徑在tools---options---projects and soulutions---show libraray的目錄下,至于這些目錄如何檢視,在以前的部落格中有相關的文章,這樣可以友善編譯器編譯時候查找到這個庫檔案)

之後把庫頭檔案拷貝到目前目錄下
在libtest的實作檔案中,首先包含這個頭檔案,然後使用pragma指令指明連結庫chang.lib,然後再工程中使用這個函數中的庫就可以了

第二種方法:

這個庫檔案可以在任意路徑下,首先在tools---options---projects and soulutions---show libraray目錄下添加這個庫檔案所在的目錄
然後再在工程屬性---configuration properties---Linker---Addtional library directories下添加這個庫檔案所在的目錄

在工程屬性---configuration properties---Linker---Input---Addtional dependencies添加要使用的庫的名字,現在這個就是chang.lib
之後把庫檔案的頭檔案拷貝到libtest工程的源檔案檔案夾下
最後在源檔案中就可以不使用pragma指令了      

//另注:生成 .lib檔案的工程中可以沒有main()函數。

//另注:工程test1之是以生成的是 .lib檔案而不是 .dll檔案,是因為test1與test2在同一個解決方案中,沒有涉及外部接口。

 實驗表明:lib庫方法二像opencv的配置方式,正确。

注意:這個時候會再解決方案檔案夾下的debug或release檔案夾下生成test1工程的.lib檔案test1.lib,在進行編譯的時候會将這個靜态庫的東西完全連結進入exe可執行檔案,這樣生成的可執行檔案可以拷貝出來到任何其他windows平台的計算機上就可以運作;一個缺點就是如果代碼很大的話,生成的.exe可執行檔案會很大,靜态連結方式就是會再編譯的時候把所有需要的東西編譯連結進可執行程式;

如果使用生成的.dll,這樣生成的exe會相對小一些,但是如果将這個可執行檔案拷貝到其他windows平台的計算機上,很可能就會無法運作,就需要把這個生成的dll檔案拷貝到運作該程式的計算機上的所需要的制定目錄下才可以(一般就是system32目錄下);缺點就是比較麻煩;

記得以前做過的一次作業就是這樣,寫的一個MFC的應用程式,拷貝到别人電腦上死活跑不住,結果發現預設的編譯方式是動态連結編譯方式,之後設定成靜态連結進行重編譯,發現生成的可執行檔案有了數倍的增長,但是放到别人的windows平台的計算機上就很順利地運作了。

參考:

在同一個解決方案下,如何從一個工程中調用另外一個工程的函數

導出C函數的:

LIB的:

vs下制作和使用.lib靜态庫

DLL的:

DLL編寫教程 - MDA之路

C/C++基本文法學習

STL

C++ primer

繼續閱讀