2013-04-10 46 views
0

我已經閱讀了有關共享和靜態庫相關教程,如:在創建共享庫期間的不同情況下,可以使用lib調用哪些函數?

"Creating a shared and static library with the gnu compiler [gcc]"

"Static, Shared Dynamic and Loadable Linux Libraries"

然而,不幸的是,他們所使用的所有例子是一個功能一個.c文件。

我有兩個問題:

(1)如果我有一個文件有兩個更多的功能,如example1.c

void ctest11(int *i) 
{ *i = 5; } 

void ctest12(int *i) 
{ *i = 5; } 

編譯exmaple1.c後libexample1.so,我可以調用ctest11和ctest12呢?

(2)如果我有一個文件具有兩個更多的功能,它們中的一個是主功能,例如example2.c

void ctest21(int *i) 
{ *i = 5; } 

void main(int *i) 
{ *i = 5; } 

編譯exmaple2.c到libexample2.so之後,是它的與僅用ctest21函數編譯一個.c文件相同?

(3)如果我有一個文件example3.c中和exmaple4.c 在example3.c中的funcion將使用功能在example4.c 例如: example3.c中

void ctest31(int *i) 
{ *i = ctest41(2,3); } 

範例4 .C

int ctest41(int a, int b) 
{ return a+b; } 

當我編譯example2.c和example3.c中以libexample23.so,我可以打電話都ctest31和ctest41?

但是,如果gcc example2.c example3.o到libexample2.so,我想我只能調用ctest31?

+0

你確定要問真正的問題嗎?你的真正動機是什麼? (爲什麼'libexample2'中的'main'?) – 2013-04-10 19:03:41

回答

1

你應該看看(並建立)一些現有的免費軟件庫,編譯它,並研究它的代碼和構建過程。

一般情況下,一個共享對象可以從幾個C源文件src1sh.csrc2sh.c ....很多時候,編譯通過製造商驅動程序進行,通常GNU make

首先,你需要每編譯共享對象的源文件爲position-independent-code(PIC),例如

gcc -Wall -fPIC src1sh.c -c -o src1sh.pic.o 
gcc -Wall -fPIC src2sh.c -c -o src2sh.pic.o 

你可能要添加-ggcc標誌用於調試目的。一旦您的程序和共享對象無bug,因爲您已使用gdbvalgrind進行了調試,請將-O2改爲gcc以使它們得到優化。

然後你需要如果你的意圖是將所有這些PIC目標文件鏈接成一個單一的共享對象(*.so文件),像

gcc -shared src1sh.pic.o src2sh.pic.o -o shared.so 

,使共享庫調用它lib*.so例如libfoo.so,並將其作爲-lfoo標記指向使用共享庫的鏈接gcc命令。

注意,鏈接共享對象也可以鏈接到其他的共享庫,所以你可以做

gcc -shared src1sh.pic.o src2sh.pic.o -lsome -o shared.so 

一些libsome.so鏈接到您的shared.so

你通常不包含編譯一個共享對象(記住main是一個非常特殊的功能,具體描述在C標準中,並且從gcc鏈接到每個程序的啓動代碼crt*.o中調用)。這幾乎是無意義的(就像你的libexample2.so)。您的main在您的程序中定義(您的程序可執行文件不需要PIC代碼)。如果你的程序是從源文件src1pr.csrc2pr.c(定義main)讓你先編譯它們作爲

gcc -Wall src1pr.c -c -o src1pr.o 
gcc -Wall src2pr.c -c -o src2pr.o 

,你將它們鏈接所有例如

gcc src1pr.o src2pr.o -o prog -lshared 

其中-lshared指的是共享庫libshared.so(你可能想編譯和-g鏈接程序文件的調試信息,你可能想傳遞額外-I標誌爲包括目錄,-L標誌圖書館目錄,如-L.搜索庫在當前目錄中...)

有辦法在運行時一些共享對象動態鏈接,特別是對於具有plugins。然後,您想要使用這種功能(並且通常希望將主程序與-rdynamic標誌鏈接起來)。

您可以在共享對象內調用(從您的程序)任何可見函數。您可能想要玩visibilityfunction attribute,例如限制共享對象內某些函數的可見性。您可能想要稍後使用constructor屬性作爲共享對象內的函數在初始化時被提前調用(如果它是插件,則在其dlopen時間)。

閱讀Program Library HowtoLevine's "Linkers and Loaders" book瞭解更多信息。 Linux共享對象(以及可重定位對象*.o和可執行二進制文件)位於Executable & Linkable Format(ELF是行業標準)。 Application Binary Interface(特別是您的處理器的ABI補充,例如AMD64 ABI supplement)中描述了一些進一步的細節。

PS。您確實希望像GNU 這樣的構建器能夠將合併爲所有這些步驟,因此請閱讀其文檔。您可能想要通過-vgcc瞭解它在做什麼...

0

感謝巴西爾的很好的解釋。 (1)對於我的第一個問題(1),在一個目標文件中有多個函數。我可以在libexample1.so中調用ctest11和ctest12so

我可以設置對libexample1.so中函數的可見性。 (b)對於我的第三個問題(3),第一個場景與從兩個目標文件創建一個庫有關。我可以調用文件中的任何函數。 第二種情況與創建庫和與另一個庫的鏈接有關。我可以調用庫中的任何函數,包括鏈接庫。

(3)我仍然不明白具有主函數的情況。 你說:「你通常不會編譯一個包含main的共享對象;這幾乎是無意義的(就像你的libexample2.so)。」

我知道這是無意義的。但是,如果我不想更改程序文件,並且想將其編譯到庫中,比如說,在example2.c中,我將它編譯爲example2.so,並且要調用函數ctest21。 我可以這樣做嗎?

example2.c

void ctest21(int *i) 
{ *i = 5; } 

void main(int *i) 
{ *i = 5; } 

我把它編譯成一個庫。

gcc -fPIC -g -c -Wall example2.c 
gcc -shared -o libexample2.so example2.o 

我想我可以在example2.o中調用crest21函數。但主要功能是無用的。 我的理解是否正確?

+0

爲什麼在你的'libexample2.so'中需要'main'函數?你的問題背後有什麼動機?你爲什麼要這麼做? (根據C標準,'main' *不能*接受一個'int * i'形式參數!您可以用'-Dmain = foo'編譯'example2.c'以將'main'重命名爲別的東西。 ..)。 – 2013-04-10 18:35:34

+0

對不起。 http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html中的教程使用void ctest1(int * i)。無論如何,我只是想知道如果我把它放在主要位置,會發生什麼?沒有動機,除非我想知道在極端情況下的結果。 – user1914692 2013-04-10 22:29:21

+0

我很好奇製作圖書館的內部機制。例如,如何組織信息,如何找到函數的入口點。有沒有什麼好的教程?謝謝。 – user1914692 2013-04-10 22:31:01

相關問題