溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

制作靜態(tài)、動(dòng)態(tài)鏈接庫(kù)

發(fā)布時(shí)間:2020-06-22 15:06:01 來(lái)源:網(wǎng)絡(luò) 閱讀:406 作者:code_小生 欄目:編程語(yǔ)言

一前言.
在windows下,靜態(tài)鏈接庫(kù)文件后綴是.lib, 動(dòng)態(tài)鏈接庫(kù)文件后綴是.dll
在linux下,靜態(tài)鏈接庫(kù)文件后綴是.a, 動(dòng)態(tài)鏈接庫(kù)文件后綴是.so

二.linux下的靜態(tài)鏈接庫(kù)(暫不說(shuō)windows下的dll)
1.新建一個(gè)printf.c 和 printf.h文件,在printf.c文件寫(xiě)上相應(yīng)的測(cè)試函數(shù),以及在.h文件中聲明。
2.新建一個(gè)makefile文件,在makefile中寫(xiě):

                all:
                    gcc printf.c -o printf.o -c
                    ar -rc libprintf.a printf.o

                clean:
                    rm -rf *.o *.a
            備注:-o參數(shù)用于指定輸出(out)文件名。不用-o的話,一般會(huì)在當(dāng)前文件夾下生成默認(rèn)的a.out文件作為可執(zhí)行程序。
                                 -c參數(shù)表示只編譯(compile)源文件但不鏈接,會(huì)把.c或.cc的c源程序編譯成目標(biāo)文件。咱們這里是生成庫(kù)文件,所以也不需要鏈接。
                                 使用ar工具進(jìn)行打包成.a歸檔文件, -r將文件插入備存文件中, -c建立備存文件。
                                 這里注意 庫(kù)名不能隨便亂起,一般是lib+庫(kù)名稱,后綴名是.a表示是一個(gè)歸檔文件,制作出來(lái)了靜態(tài)庫(kù)之后,發(fā)布時(shí)需要發(fā)布.a文件和.h文件。

                至此靜態(tài)鏈接庫(kù)就制作完成。那如何引用它呢?

                    1.我們將上面制作好的libprintf.a文件和printf.h復(fù)制到一個(gè)新的test文件夾中。再新建一個(gè)test.c文件和一個(gè)makefile文件。
                            注意:test.c中頭文件應(yīng)包含printf.h------>#include "printf.h" //(注意雙引號(hào))

                            然后寫(xiě)好main函數(shù),在main函數(shù)中調(diào)用printf.c中寫(xiě)好的測(cè)試函數(shù)。

                        2.接下來(lái)就是寫(xiě)makefile
                                `
                                    all:
                                        gcc test.c -lprintf -L.
                                        #注意-L后面的.

                                    clean:
                                        rm -rf *.o *.out
                                    `
                                    -l參數(shù)就是用來(lái)指定程序要鏈接的庫(kù),-l參數(shù)緊接著就是庫(kù)名,那么庫(kù)名跟真正的庫(kù)文件名有什么關(guān)系呢?就拿數(shù)學(xué)庫(kù)來(lái)說(shuō),他的庫(kù)名是m,他的庫(kù)文件名是libm.so,很容易看出,把庫(kù)文件名的頭lib和尾.so去掉就是庫(kù)名了。
                                    -L .,表示將當(dāng)前目錄作為第一個(gè)尋找?guī)煳募哪夸洠?尋找的順序是:./–>/lib–>/usr/lib–>/usr/local/lib

                                    注意:編譯時(shí),必須得告訴編譯器靜態(tài)鏈接庫(kù)的名字和路徑(沒(méi)告訴的話會(huì)去默認(rèn)路徑下查找),這點(diǎn)也很容易理解。
                        3.編譯后 執(zhí)行a.out文件,即輸出printf.c中測(cè)試函數(shù)的內(nèi)容,整個(gè)下來(lái)就是靜態(tài)鏈接庫(kù)的制作和使用。

三.linux下的動(dòng)態(tài)鏈接庫(kù)
1.同樣新建一個(gè)printf.c printf.h 和makefile
2.makefile中編寫(xiě)如下:
gcc printf.c -o printf.o -c -fPIC<br/>gcc -o libprintf.so printf.o -shared <br/>
-fPIC參數(shù)是位置無(wú)關(guān)碼,-shared參數(shù)是按照共享庫(kù)的方式來(lái)鏈接。

                    此時(shí)生成的libprintf.so文件即動(dòng)態(tài)鏈接庫(kù)文件,那么在發(fā)布的時(shí)候,發(fā)布libprintf.so和printf.h文件即可

                3.同樣新建一個(gè)test文件,將libprintf.so與printf.h文件復(fù)制進(jìn)去,新建一個(gè)test.c與makefile文件。
                4.makefile寫(xiě)法與靜態(tài)鏈接庫(kù)一致
                                                            `
                                    all:
                                        gcc test.c -lprintf -L.
                                        #注意-L后面的.

                                    clean:
                                        rm -rf *.o *.out
                                    `
                        但是由于靜態(tài)鏈接與動(dòng)態(tài)鏈接實(shí)現(xiàn)的機(jī)制不同,具體哪些不同,請(qǐng)自行百度搜索,很多。
                        這里直接去執(zhí)行./a.out是執(zhí)行不成功的
                        報(bào)錯(cuò)誤:
                            error while loading shared libraries: libprintf.so: cannot open shared object file: No such file or directory

                        原因是使用動(dòng)態(tài)鏈接庫(kù)時(shí),需要臨時(shí)加載動(dòng)態(tài)鏈接庫(kù),而不是在編譯時(shí)將庫(kù)里面的內(nèi)容加載出來(lái),編譯到一起。這是與靜態(tài)鏈接庫(kù)不同的地方。所以,它這里找不到庫(kù)文件在哪里,那么有一下幾種解決辦法:
                        (1)將libprintf.so放到固定目錄下就可以了,這個(gè)固定目錄一般是/usr/lib目錄。 cp libprintf.so /usr/lib即可
                        (2)使用環(huán)境變量LD_LIBRARY_PATH。操作系統(tǒng)在加載固定目錄/usr/lib之前,會(huì)先去LD_LIBRARY_PATH這個(gè)環(huán)境變量所指定的目錄下去尋找,如果找到就不用去/usr/lib下面找了,如果沒(méi)找到再去/usr/lib下面找。所以解決方案就是將libprintf.so所在的目錄導(dǎo)出到環(huán)境變量LD_LIBRARY_PATH中即可。

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: + 文件所在的路徑。
5.再去執(zhí)行a.out即可執(zhí)行成功。

四.總結(jié)
1.咱們注意到靜態(tài)鏈接庫(kù)與動(dòng)態(tài)鏈接庫(kù)中 test文件夾中makefile,都有一句gcc test.c -lprintf -L,注意這個(gè)-lprintf參數(shù),假如在文件夾中,又有靜態(tài)鏈接庫(kù),又有動(dòng)態(tài)鏈接庫(kù),那編譯器該如何選擇呢? 答案是會(huì)優(yōu)先選擇動(dòng)態(tài)鏈接庫(kù)文件。
2.還有個(gè)nm命令也很有用,它可以用來(lái)查看一個(gè).a或者.so文件中都有哪些符號(hào),簡(jiǎn)單來(lái)說(shuō)就是看有哪些函數(shù)。
3.ldd命令(動(dòng)態(tài)鏈接庫(kù)):作用是可以在一個(gè)使用了共享庫(kù)的程序執(zhí)行之前解析出這個(gè)程序使用了哪些共享庫(kù),并且查看這些共享庫(kù)是否能被找到,能被解析(決定這個(gè)程序是否能正確執(zhí)行)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI