如何電腦上共享代碼
如果你在同一臺計算機上做編程工作,你想在多個程序中使用相同的代碼,但又不想每個程序都保留一份相同的代碼。那么最好的做法就是共享這部分代碼,我們可以在程序之間共享兩類代碼:.h頭文件和.o目標文件。
那么應該怎么共享呢?
共享.h頭文件
有兩種方式:
1.把.h頭文件保存在標準目錄中,在類Unix系統中,標準目錄就是/usr/local/include
只要頭文件在標準目錄中,就可以用尖括號包含它們,如共享.encrypt.h文件:
~$mv encrypt.h /usr/local/include //在代碼中包含頭文件 #include
1
2
3
2.把頭文件放在非標準目錄中,在使用時,就要用完整的路徑名,不能使用尖括號,如:
~/Desktop/Mc$ mkdir ~/my_head_file ~/Desktop/Mc$ mv encrypt.h ~/my_head_file //在代碼中包含頭文件 #include "/home/wong/my_head_file/encrypt.h"
1
2
3
4
5
如果你沒有使用完整路徑名引用頭文件,就要告訴編譯器去哪里找頭文件:
如果此時頭文件中/home/wong/my_head_file中,如test.c文件中是如此#include "encrypt.h"包含了此頭文件,那么就要這樣編譯:
$ gcc -I/home/wong/my_head_file encrypt.c checksum.c test.c -o test
1
注:-I就是告訴編譯器去哪里找頭文件的
共享.o目標文件
1.可以把.o目錄文件放在一個目錄下,所以編譯時,只在目標文件前加上完整路徑即可:
~/Desktop/Mc$ mkdir ~/my_object_file ~/Desktop/Mc$ mv encrypt.o checksum.o ~/my_object_file ~/Desktop/Mc$ gcc -I/home/wong/my_head_file test.c /home/wong/my_object_file/encrypt.o /home/wong/my_object_file/checksum.o -o test
1
2
3
但是上面這種共享會讓人很累,如果一兩個還好,多了的話,就那是受罪,因此提供另外一種方法,就是將目標文件存檔,即將一批目標文件打包在一起,然后就可以一次告訴編譯器一批目標文件了。
存檔文件的后綴名是.a。
存檔文件的標準命名方式是libXXX.a的形式。
存檔是靜態庫,編譯時會把代碼放到你的程序中,文章后面會價紹動態庫。
用ar命令創建存檔:
~/Desktop/Mc$ ar -rcs libencrypchecksum.a encrypt.o checksum.o
1
介紹一下參數:
r:表示如果.a文件存在就更新它。
c:創建存在時不顯示反饋信息
s: 告訴ar要在.a文件開頭建立索引
.a存檔文件可以放哪里呢?
1.可以放在標準目錄/usr/local/lib,編譯就無需要告訴編譯器要去哪里找存檔文件:
~/Desktop/Mc$ gcc test.c -lencrypchecksum -o test
1
2.還可以放在其他目錄中,編譯就需要告訴編譯器要去哪里找存檔文件。
~/Desktop/Mc$ mkdir ~/my_lib ~/Desktop/Mc$ mv libencrypchecksum.a ~/my_lib ~/Desktop/Mc$ gcc -I/home/wong/my_head_file test.c -L/home/wong/my_lib -lencrypchecksum -o test
1
2
3
-L參數就是告訴編譯器去哪里找存檔文件的。
-l參數后就是跟存檔名,注意存檔名是去掉了lib和.a的部分。
如果想從存檔文件中提取目標文件,也是可以的,如我們提取encrypt.o文件,方法如下:
~/my_lib$ ar -x libencrypchecksum.a encrypt.o ~/my_lib$ ls encrypt.o libencrypchecksum.a
1
2
3
這樣encrypt.o文件就被提取出來了。
上面就是共享.h頭文件和.o目標文件的方法。
上面的編譯都是靜態編譯,或者說是靜態鏈接,一旦鏈接了就不能更改了,也就是說,這些目錄文件的代碼被包含進程序,如果要修改這些目標文件,那程序只能重新編譯了。
但是如果這些目標文件做成動態庫,那問題很好辦了。動態庫與存檔很像,不同的地方就是在動態庫中,目標文件會鏈接成一段目標代碼。動態庫有上些額外信息,操作系統需要用這些信息把庫連接到程序。
因為庫是動態的,所以使用動態庫編譯時,編譯器不會在可執行文件中包含庫代碼,即目標文件的代碼不會被包含進程序,而是會在可執行文件中插入一段用來查找庫的“占位符”代碼,并在運行時鏈接庫。
動態庫在不同平臺有不同叫法:
在Linux和Unix上叫共享目標文件,后綴名是.so
在Mac平臺上,叫動態庫,后綴名是.dylib
在Windows平臺上,叫動態鏈接庫,后綴名是.dll
我們開始創建動態庫吧。
1.首先創建目標文件:
~/Desktop/Mc$ gcc -I/home/wong/my_head_file -fPIC -c encrypt.c ~/Desktop/Mc$ gcc -I/home/wong/my_head_file -fPIC -c checksum.c
1
2
-c:表示不要鏈接代碼
-fPIC:告訴gcc編譯器創建位置無關代碼
位置無關的代碼就是無論計算機把它加載到存儲器的哪個位置都可以運行的代碼。例如,有個動態庫,它要加載800個字節外的某個全局變量的值,如果操作系統把動態庫載到其他地方,就會出錯,只有創建了位置無關的動態庫才能解決此問題。
有的操作系統和處理器要用位置無關代碼創建庫,這樣它們才能在運行時決定把代碼加載到存儲器的哪個位置。事實上大多數操作系統都不需要加這個選擇。
2.創建動態庫
我們把ecnrypt.o和checksum.o編進動態庫里去
~/Desktop/Mc$ gcc -shared encrypt.o checksum.o -o libencryptchecksum.so
1
-shared選項就是告訴gcc我們想把.o目標文件轉化為動態庫。
linux和Unix平臺上動態庫的標準命名方式是:libXXX.so
注意:上面創建了一個叫libencryptchecksum.so的庫,那么libencryptchecksum.so文件就會記錄它的庫名叫encryptchecksum,就是說一旦用了某個名字編譯了動態庫,就不能再修改文件名了。若想重命名庫,就必須用新的名字重新編譯一次。
3.用動態庫編譯程序
~/Desktop/Mc$ gcc -I/home/wong/my_head_file -c test.c -o test.o ~/Desktop/Mc$ gcc test.o -L/home/wong/my_lib -lencryptchecksum -o test ~/Desktop/Mc$ ./test ./test: error while loading shared libraries: libencryptchecksum.so: cannot open shared object file: No such file or directory
1
2
3
4
成功編譯了,但是運行的時候出錯了!!!
原因:在Linux和大部分Unix中,編譯器只會記錄libencryptchecksum.so庫的文件名,而不會記錄路徑名。
如果不是把動態庫保存到標準庫/usr/lib中,程序就會找不到它,為了解決這個問題,Linux會檢查保存在LD_LIBRARY_PATH變量中的附加目錄,只要把庫目錄添加到這LD_LIBRARY_PATH中,并export它,程序就能找到libencryptchecksum.so庫了。
~/Desktop/Mc$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/my_lib ~/Desktop/Mc$ ./test !!!!!
1
2
3
這樣就可以了,另外提醒一點,在命令行export只是臨時的,一關掉命令行(終端)就沒有了。要永久的話,可以在/etc/profile或~/.profile或 /home/wong/.bashrc等配置文件中配置。
靜態鏈接和動態鏈接哪個好呢,使用靜態鏈接可以得到一個小而快的可執行文件,可以很方便地從一臺機器拷貝到另一臺機器,而而動態鏈接允許在運行時配置程序。一般驅動都會做成動態庫。
Linux Unix
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。