『壹』 介紹靜態鏈接庫和動態鏈接庫的區別,及在VC+
靜態連接庫就是把(lib)文件中用到的函數代碼直接鏈接進目標程序,程序運行的時候不再需要其它的庫文件;動態鏈接就是把調用的函數所在文件模塊(DLL)和調用函數在文件中的位置等信息鏈接進目標程序,程序運行的時候再從DLL中尋找相應函數代碼,因此需要相應DLL文件的支持。
靜態鏈接庫與動態鏈接庫都是共享代碼的方式,如果採用靜態鏈接庫,則無論你願不願意,lib 中的指令都全部被直接包含在最終生成的 EXE 文件中了。但是若使用 DLL,該 DLL 不必被包含在最終 EXE 文件中,EXE 文件執行時可以「動態」地引用和卸載這個與 EXE 獨立的 DLL 文件。靜態鏈接庫和動態鏈接庫的另外一個區別在於靜態鏈接庫中不能再包含其他的動態鏈接庫或者靜態庫,而在動態鏈接庫中還可以再包含其他的動態或靜態鏈接庫。動態庫就是在需要調用其中的函數時,根據函數映射表找到該函數然後調入堆棧執行。如果在當前工程中有多處對dll文件中同一個函數的調用,那麼執行時,這個函數只會留下一份拷貝。但是如果有多處對lib文件中同一個函數的調用,那麼執行時,該函數將在當前程序的執行空間里留下多份拷貝,而且是一處調用就產生一份拷貝。
靜態鏈接庫與靜態鏈接庫調用規則總體比較如下:
1、靜態鏈接庫(比較簡單):
首先,靜態鏈接庫的使用需要庫的開發者提供生成庫的.h頭文件和.lib文件。生成庫的.h頭文件中的聲明格式如下:
extern "C"函數返回類型函數名(參數表);
在調用程序的.cpp源代碼文件中如下:
#include "../lib.h"
#pragma comment(lib,"..//debug//libTest.lib")//指定與靜態庫一起鏈接
其次因為靜態鏈接庫是將全部指令都包含入調用程序生成的EXE文件中。因此如果用的是靜態鏈接庫,那麼也就不存在「導出某個函數提供給用戶使用」的情況,要想用就得全要!要不就都別要!
靜態鏈接庫(Lib)
在VC++6.0中new一個名稱為libTest的static library工程,並新建lib.h和lib.cpp兩個文件,lib.h和lib.cpp的源代碼如下:
//文件:lib.h
#ifndef LIB_H
#define LIB_H
extern "C" int add(int x,int y);//聲明為C編譯、連接方式的外部函數
#endif
//文件:lib.cpp
#include "lib.h"
int add(int x,int y)
{ return x + y; }
編譯這個工程就得到了一個.lib文件,這個文件就是一個函數庫,它提供了add的功能。將頭文件和.lib文件提交給用戶後,用戶就可以直接使用其中的add函數了。
標准Turbo C2.0中的C庫函數(我們用來的scanf、printf、memcpy、strcpy等)就來自這種靜態庫。
下面來看看怎麼使用這個庫,在libTest工程所在的工作區內new一個libCall工程。libCall工程僅包含一個main.cpp文件,它演示了靜態鏈接庫的調用方法,其源代碼如下:
#include <stdio.h>
#include "../lib.h"//不可丟失
#pragma comment( lib, "..//debug//libTest.lib" ) //指定與靜態庫一起連接
int main(int argc, char* argv[])
{ printf( "2 + 3 = %d", add( 2, 3 ) ); }
靜態鏈接庫的調用就是這么簡單,或許我們每天都在用,可是我們沒有明白這個概念。代碼中#pragma comment( lib , "..//debug//libTest.lib" )的意思是指本文件生成的.obj文件應與libTest.lib一起連接
2、 動態鏈接庫:
動態鏈接庫的使用需要庫的開發者提供生成的.lib文件和.dll文件。或者只提供dll文件。
首先我們必須先注意到DLL內的函數分為兩種:
1)外部函數,可供應用程序調用;
2)DLL內部函數,只能在DLL程序使用,應用程序無法調用它們。
因此調用程序若想調用DLL中的某個函數就要以某種形式或方式指明它到底想調用哪一個函數。
動態庫函數的調用,可以採用靜態鏈接的方式,主要步驟如下:
1)包含DLL中導出的頭文件。
2)採用#pragma comment(lib,"..//debug//libTest.lib")導入動態庫生成的*.lib頭文件。或在projectàsettingsàLinkeràInput的Additional Dependencies中加入lib文件。
3)將動態庫生成的*.dll文件放到EXE或DLL的同一目錄下。
也可以採用動態載入的方式調用,步驟如下:
Another.dll有一個int Add(int x,int y)函數。則完整的調用過程如下:
typedef int (* FunPtr)(int,int);//定義函數指針
FunPtr funPtr;
Handle handle =LoadLibrary("Another.dll");
funPtr =(FunPtr)GetProcAddress(handle ,"Add");
funPtr(2,3);// 2+3;
FreeLibrary(handle);//釋放載入的動態庫
二、LIB文件
目前以lib後綴的庫有兩種,一種為靜態鏈接庫(Static Libary,以下簡稱「靜態庫」),另一種為動態連接庫(DLL,以下簡稱「動態庫」)的導入庫(Import Libary,以下簡稱「導入庫」)。
靜態庫是一個或者多個obj文件的打包,所以有人乾脆把從obj文件生成lib的過程稱為Archive,即合並到一起。比如你鏈接一個靜態庫,如果其中有錯,它會准確的找到是哪個obj有錯,即靜態lib只是殼子。
動態庫一般會有對應的導入庫,方便程序靜態載入動態鏈接庫,否則你可能就需要自己LoadLibary調入DLL文件,然後再手工GetProcAddress獲得對應函數了。有了導入庫,你只需要鏈接導入庫後按照頭文件函數介面的聲明調用函數就可以了。
導入庫和靜態庫的區別很大,他們實質是不一樣的東西。靜態庫本身就包含了實際執行代碼、符號表等等,而對於導入庫而言,其實際的執行代碼位於動態庫中,導入庫只包含了地址符號表等,確保程序找到對應函數的一些基本地址信息。
這也是實際上很多開源代碼發布的慣用方式:
1、預編譯的開發包:包含一些.dll文件和一些.lib文件。其中這里的.lib就是導入庫,而不要錯以為是靜態庫。但是引入方式和靜態庫一樣,要在鏈接路徑上添加找到這些.lib的路徑。而.dll則最好放到最後產生的應用程序exe執行文件相同的目錄。這樣運行時,就會自動調入動態鏈接庫。
2、用戶自己編譯:下載的是源代碼,按照readme自己編譯。生成很可能也是.dll + .lib(導入庫)的庫文件
3、如果你只有dll,並且你知道dll中函數的函數原型,那麼你可以直接在自己程序中使用LoadLibary調入DLL文件,GetProcAddress獲取函數地址,然後調用。
三、DLL文件
動態鏈接庫(DLL)是作為共享函數庫的可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬於其可執行代碼的函數。函數的可執行代碼位於一個DLL中,該DLL包含一個或多個已被編譯、鏈接並與使用它們的進程分開存儲的函數。DLL還有助於共享數據和資源。多個應用程序可同時訪問內存中單個DLL副本的內容。
動態鏈接與靜態鏈接的不同之處在於它允許可執行模塊(.dll文件或.exe文件)僅包含在運行時定位DLL函數的可執行代碼所需的信息。在靜態鏈接中,鏈接器從靜態鏈接庫獲取所有被引用的函數,並將庫同代碼一起放到可執行文件中。
使用動態鏈接代替靜態鏈接有若干優點。DLL節省內存,減少交換操作,節省磁碟空間,更易於升級,提供售後支持,提供擴展MFC庫類的機制,支持多語言程序,並使國際版本的創建輕松完成。
1 靜態鏈接庫的優點
(1) 代碼裝載速度快,執行速度略比動態鏈接庫快;
(2) 只需保證在開發者的計算機中有正確的.LIB文件,在以二進制形式發布程序時不需考慮在用戶的計算機上.LIB文件是否存在及版本問題,可避免DLL地獄等問題。
2 動態鏈接庫的優點
(1) 更加節省內存並減少頁面交換;
(2) DLL文件與EXE文件獨立,只要輸出介面不變(即名稱、參數、返回值類型和調用約定不變),更換DLL文件不會對EXE文件造成任何影響,因而極大地提高了可維護性和可擴展性;
(3) 不同編程語言編寫的程序只要按照函數調用約定就可以調用同一個DLL函數;
(4)適用於大規模的軟體開發,使開發過程獨立、耦合度小,便於不同開發者和開發組織之間進行開發和測試。
3 不足之處
(1) 使用靜態鏈接生成的可執行文件體積較大,包含相同的公共代碼,造成浪費;
(2) 使用動態鏈接庫的應用程序不是自完備的,它依賴的DLL模塊也要存在,如果使用載入時動態鏈接,程序啟動時發現DLL不存在,系統將終止程序並給出錯誤信息。而使用運行時動態鏈接,系統不會終止,但由於DLL中的導出函數不可用,程序會載入失敗;速度比靜態鏈接慢。當某個模塊更新後,如果新模塊與舊的模塊不兼容,那麼那些需要該模塊才能運行的軟體,統統撕掉。這在早期Windows中很常見。
『貳』 如何編譯 opencv動態鏈接庫
在一個項目中需要用到OpenCV,剛開始使用了OpenCV的動態鏈接庫,這樣,在移動可執行程序時還必須將OpenCV動態支持庫一起搬移,很是麻煩。所以,最終選擇OpenCV靜態鏈接庫,這樣程序移植運行就方便了很多。
需要編譯成靜態庫以便於應用程序鏈接。
網上有的教程中寫的在VC++2010下安裝OpenCV2.1時用到了TBB庫,而我在編譯鏈接自己的程序後需要用到TBB.dll。本人設計的目的就是要做一個獨立的界面程序,不需要攜帶其他第三方庫。經過一段時間的努力最終找到了編譯OpenCV2.1靜態庫的方法。
『叄』 c++ 關於動態鏈接庫編譯的問題
出現一個Executable For Debug Session對話框
---------------------------------------------
當你出現這個對話框時,是提示你應該選擇一個.exe文件用來測試。
如果要設置的話:依次在主菜單中,工程-->設置-->debug下就可以看到這個對話框的設置了。
提示沒有可執行文件來測試這個DLL文件。
因為,DLL文件自己是不能執行的,所以需要一個可執行文件(.exe)來載入它來測試。
『肆』 動態鏈接,靜態鏈接 動態編譯,靜態編譯 動態鏈接庫,靜態鏈接庫 這些兩兩間的區別是什麼呢
有點兒亂……,分數少簡單扼要的說說吧。
————————————
首先,傳統的編譯,也就是靜態編譯是把 源文件 翻譯成目標文件,這個是一次性過程,也就是你所謂的靜態編譯。
後來的Java和.NET等語言,首先編譯成中間形式,然後運行過程中根據需要編譯成本地代碼(注意這個過程不是一次性的,下次運行重新編譯),這個就是JIT(即時編譯)技術,從即時編譯發展出了動態編譯技術
————————————
(傳統的)編譯完成後,像C/C++、Fortran、匯編等語言,可以把多個目標文件合並到一個庫文件中,這個就是靜態庫。比如常說的庫函數printf就是libc裡面的函數。
如果有了啟動函數(main),main裡面使用了printf,就可以通過靜態鏈接技術,從libc中提取出printf所在的文件加入到可執行文件中,如果printf還需要其它函數,就繼續搜索並加入列表,直到形成一個閉包。這個就是靜態鏈接。
可是靜態鏈接有個明顯的缺點,如果每個程序都需要printf,那麼printf這個函數的代碼就會同時存在在每個程序中,這樣也太佔地方了吧。所以發明了動態連接技術,其實有兩種形式。無論哪一種,都是首先記錄下需要調用printf這個函數以及所在的動態庫,等到運行的時候再載入動態庫,從動態庫中找到真正的printf去執行。
由於,動態鏈接技術需要一些額外的信息,傳統的靜態庫是不具備的,這些額外信息主要是重復載入和卸載時所需要的一些代碼,因此需要動態鏈接庫。
『伍』 靜態編譯和動態編譯有何不同
靜態編譯就是把庫函數編譯到你的程序里 這樣編譯的好處是 可以適應不同的平台 如果你是用window系統的話不建議用靜態編譯 因為這樣會使你的代碼量增大
動態編譯就是不把庫函數編譯到你的程序里
『陸』 求教:aix下動態鏈接庫*.so文件如何編譯出來
先檢查你的編譯器是什麼編譯器:
看是gcc還是cc,下面是cc版本的
編譯成32位版本:
cc -q32 -qmkshrobj -o XXXXXX.so XXXXXX.c
編譯成64位版本:
cc -q64 -qmkshrobj -o XXXXXX.so XXXXXX.c
『柒』 怎樣將自己做的動態鏈接庫「靜態」編譯到可執行文件里
舉例文件:add.c
gcc -fPIC -c add.c /生成.o文件
gcc -shared add.o -o libmath.so /載入add.o到math動態庫
gcc test.c -L. -Lmath /test.c 為主程序
另外;配置動態庫載入器環境變數:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
『捌』 求助,依賴的動態庫包含靜態庫,編譯報錯說找
動態鏈接庫和靜態鏈接庫一般是編譯集成一系列的介面(函數)
在程序源代碼編譯完成後通過編譯器編譯並通過鏈接器與這些庫進行鏈接
動態鏈接庫與靜態鏈接庫的區別在於鏈接器在進行鏈接時靜態庫會被直接編譯進程序里
而動態鏈接庫並不會,我們這里將這些鏈接庫稱作依賴(動態庫和靜態庫)
程序的運行需要這些依賴,程序在靜態鏈接後該程序本身便已包含該依賴
而動態鏈接後的程序本身本不包含該依賴,這些依賴需要執行者自行安裝進操作系統(動態庫、運行時庫)
程序運行時會動態地載入這些庫
linux上動態庫一般的後綴後為.so
靜態庫一般的後綴為.a
由於靜態鏈接會直接將庫編譯進程序里所以靜態編譯後的程序相較於動態鏈接所要大
這就是因為靜態鏈接會將鏈接庫編譯進程序里的原因,所以佔用就要大了
出於這種原因,靜態庫不易於維護與更新,如果鏈接庫中有實現有bug等需要更新則需要更新整個程序,因為靜態庫被編譯進程序中了
但動態庫就沒有這種情況了,因為動態庫是程序運行時動態載入的,所以我們只需要更新動態庫而不需要更新所有依賴該庫的程序(軟體)
另一方面,很多程序的開發都會使用到相同的鏈接庫,也就是很多程序(軟體)會有相同的依賴
如果將這些依賴全部靜態編譯的話將會造成存儲資源佔用過多而造成資源浪費
而使用動態庫的方式這些程序(軟體)則可以共享一個鏈接庫,而不需要每個程序都帶一個鏈接庫,這樣就大大地減少了存儲資源佔用空間
『玖』 製作DLL的源文件能不能編譯成.SO文件
純C寫的話,移植到linux應該是很容易的
順利的話直接在linux下編譯就行了,不順利的話,需要把windos下的函數替換成對應的linux下的,或者自己再封裝一層