關於各平台程式使用之連結庫類型。
-
Static libraries
-
Shared libraries
-
Dynamically loaded libraries
參考資料來源:
-
https://kaineshu.wordpress.com/2007/05/02/%E8%BD%89%E8%B2%BC%E7%94%A8gcc-%E8%87%AA%E8%A3%BD-library/
Object File :
通常副檔名為.o或是.obj,後者為Windows使用的格式。

將.c或.cpp、.cxx的C語言程式碼包裝成的物件檔,無法直接使用。
使用編譯工具的"Link"功能可以將這些單獨的物件檔合併成連結庫或是可執行檔。
Static libraries - 靜態資料庫 :
通常副檔名為.a。
作用方式:將連結庫包入程式中執行,處理效率高,缺點是檔案大且不易更新。
若要建立一個靜態資料庫,可以使用DllTool從.dll檔解出或是用GNU的ar工具連結物件檔編譯。
ar的指令中,rcs或是-r後接上輸出的檔案名稱,如下:
ar rcs libmylib.a first.o second.o
產生靜態資料庫後,可以使用gcc的-L和-l指令連結,對象包含程式碼、物件檔和其他靜態資料庫。
Shared libraries - 共用資料庫 :
通常副檔名為.so,後面可加掛版本編號。
作用方式:資料庫和執行檔是分離的,剛開始就要載入,並且資料庫必須一直和執行檔待在一起,優點是修改方便。
gcc在產生物件檔時必須加上-fPIC參數,紀錄"position-independent code",就是獨立位置碼,以紀錄存取位置的資訊。沒有使用的話只會用相對位置,不利於共享內容。
再來將物件檔合併成資料庫時,加上-shared參數,接著要自訂義"soname"、"real name"、"linker name"。
-
soname是資料庫的名稱,通常以
lib開頭,包含附檔名和大版號,如libexample.so.1。 -
real name是真正使用程式的資料庫名稱,包含小版號,如
libexample.so.1.0.0。 -
linker name是連結時的資料庫名稱,不包含版號,如
libexample.so。
gcc使用-Wl參數向內建的Link工具"ln"傳入資訊,如下:
gcc -shared -Wl,-soname,libexample.so.1 -o libexample.so.1.0.0 first.o second.o
使用-Wl,-soname定義soname;輸出的檔案名稱為real name;使用-l或-l:連結的名稱為linker name。
尋找了下維基百科,似乎也能使用-h和-soname=來定義soname的名稱。
資料庫連結時使用ln指令連結兩個.so檔。使用-s參數為軟連結,類似捷徑式的參照;使用-d參數為硬連結,類似副本的備份。
最後必須用以下指令為real name創造linker name和soname的檔案(使用-s或-d就隨喜好了)。
linker name
ln -s libexample.so.1.0.0 libexample.so
soname
ln -s libexample.so.1.0.0 libexample.so.1
之後可以用GNU的另一個工具"objdump"檢查連結。
objdump -p libexample.so.1.3 | grep SONAME
產生共用資料庫後,可以像靜態資料庫一樣包裝,也可以用程式呼叫。
連結時有同名資料庫時會以共用資料庫優先,加上-static參數可以指定靜態資料庫。
而調用資料庫時是先找soname的檔案,否則會尋找linker name的檔案,可執行檔亦同。
Dynamically loaded libraries - 動態載入庫 :
為Windows中.dll檔標準的模式,不過並非所有.dll都是如此。
作用方式:使用時才會載入,編譯時不須要相關資料庫檔案,因此常用於附加元件。
使用一套DLL function來處理,標頭檔和編譯的程式碼中都會使用來傳遞訊息。
gcc編譯時要加上-ldl參數連結。
後來發現gcc有時編譯「成功」的樣子可能包含著錯誤。

今天測試了一些方法,但是明明CDemo和Python的.so都是差不多的參數,編譯出的結果卻不如預期。
libslvs.so
g++ -shared -o libslvs.so ../obj/util.obj ... ../obj/w32util.obj
_slvs.so
g++ -shared -o _slvs.so ../obj/util.obj ... ../obj/slvs_wrap.o -LW:/Anaconda3/libs -lPython35 -L. -l:libslvs.so
如果編譯_slvs.so時不加上後面的-LW:/Anaconda3/libs、-lPython35等等就會因為slvs_wrap.o的slvs_wrap.cxx出問題,但是沒加上就和libslvs.so一樣了。
但是這樣另一個問題就產生了,因為編出來的_slvs.so是「可執行檔」,不指定-o _slvs.so的話就會編譯成a.exe,所以其他Python程式碼都找不到(有搬到虛擬機的Ubuntu測試,也找不到)。

想過學範例用.c跳過Object File的階段直接轉成.so檔,但是只有libslvs.so成功,_slvs.so反而在系統暫存檔Temp資料夾中找不到Python連結。
之後稍微看了一下SWIG轉出的slvs.py結構,呼叫的.py檔必須先導入slvs.py後,slvs.py會視Python版本取用_slvs.so的內容,再傳給需要的.py檔,所以slvs.py和_slvs.so都必須和撰寫的.py檔放在一起。
Comments
comments powered by Disqus