跟我學c 中級篇 動態庫

2021-10-24 09:07:46 字數 2495 閱讀 1819

在linux下建立動態庫的編譯選項有乙個-fpic,它的意思是與位置無關(position-independet code),那麼它有什麼意義呢?在沒有出現這個選項前,是不是就不能建立動態庫呢。答案肯定是否定的。其實這就是上面提到的發展過程中的,如果沒有這個選項,只能完全載入副本,而如果使用了這個選項就可以程序共享這個副本了。沒有這個選項前的動態庫是一種執行時載入,比較原始。而使用其以後,就多程序共享此副本,在x64平台上基本已經預設使用了。

可以這樣認為,在x32平台上,這個選項,可以忽略,在x64上不使用這個選項,在鏈結時,就會發生鏈結錯誤。那麼是不是必須使用這個選項才可以呢?也不是,可以向編譯器指定 -mcmodel=large來防止這個錯誤。

多說幾句,編譯靜態庫,是否使用這個選項,要看這個靜態庫的應用方式,如果這個靜態庫需要被動態庫使用,就要加上這個選項,否則,可以認為加不加沒有什麼影響。

動態庫的特點,本質就是二進位制介面的相容。也就是在c++程式設計中經常提到的abi,在很多c++牛人的文章中經常可以看到,一定要保持二進位制的介面的穩定性,不要使用純虛函式做為介面,就是這個原因。因為動態庫在這方面的體現的更為明顯。

c++的過載和編譯更名機制,使得c++的二進位制介面變得更為複雜,鏈結器就需要在這種複雜的情況下,保證在鏈結時能找到相關的介面。鏈結器使用一種叫做「名稱修飾」的技術來進行符號的定位。不過可惜的是,這種技術並不是標準的,這意味著不同編譯平台處理可能有所不同,甚至在某方面有很大不同,這也是為什麼有的**可以在某些編譯器正常編譯,但是有的不行的乙個外在表現。

動態庫有兩種載入方式 ,一種是載入時動態鏈結,一種是執行時動態鏈結。這個很好理解,一種是在編譯時就把動態庫編譯進來,一種是程式在啟動後,通過通用的api,比如dlopen,來開啟相關動態庫。

動態庫的應用現在已經非常廣泛,舉乙個例子,在windows的system32路徑下和linux的lib路徑下,可以看到大片的動態庫檔案(windows是以.dll為字尾, linux是以.so為字尾)。日常接觸到的最常用的應用場景就是,公司有一項技術不想為其它公司知道,但又要為其它公司提供服務,就可以把相關的**打成動態庫,再提供乙個標頭檔案。這樣,**的安全性就得到了很大的保障。下面看乙個linux下的簡單的動態庫的例子:

#include int compare(int a,int b)

else

return 0;

}

用下面的命令進行編譯:

g++ -fpic -shared -o libcompare.so compare.cpp
這裡需要說明的是,linux下的動態庫,要求必須以lib開頭,加自定義的名字再加字尾.so。否則編譯可能找不到相關的庫。

為了省事,就沒有單獨建立乙個標頭檔案,直接把函式的宣告放到了應用的檔案中。

#include int compare(int a,int b);

int main()

用下面的命令進行編譯:

g++ -o dtest testdll.cpp -l.  -lcompare
編譯完成後,看下目錄下,會發現有兩個新生成的檔案:libcompare.so 和 dtest。這時個執行一下這個檔案:

./dtest

./dtest: error while loading shared libraries: libcompare.so: cannot open shared object file: no such file or directory

發生這個的原因是在於linux下的編譯和執行時的機制的問題,在執行時沒有找到這個庫檔案,解決的方法有以下兩種方法:

1、臨時的最簡單的方法:

ld_library_path=. ./dtest 或者export ld_library_path=pwd:$ld_library_path

將庫的路徑臨時指到當前路徑。

2、將庫拷貝到/usr/lib路徑下(或相關目錄),然後在/etc/ld.so.conf(其實更多的我們自己單獨建立乙個檔案,把這個檔案掛到這個檔案中),再ldconfig即可。這種方法在實際工程中經常使用。

開啟/etc/ld.so.conf,發現其內容為:

include /etc/ld.so.conf.d/*.conf
其它不同平台可能還有不同的解決方法,這裡就不一一枚舉。

通過上面這個簡單的乙個小例子,可以了解動態庫的乙個初步開發流程,在後面會相繼展開在兩種平台下的動態庫程式設計的詳細介紹,先丟擲一塊小磚,再請同學們慢慢品嚐後面的美食。

動態庫技術是一門相對來說的複雜的技術,但也不是說有多難。整體上融會貫通之後,讓你可以從底層的角度了解記憶體的管理和定址的方式,更好的和os原理中的一些闡述相結合。知易行難,很多東西需要親手來實踐一下,才能夠明白個中的滋味。簡單的看看資料,走馬觀花一樣的瀏覽一下,是不會讓同學們成為高手。

跟我學c 中級篇 pimpl

private implementation,私有化實現。在c 中,由於語言本身的限制,沒有純粹的介面定義。這就導致了在介面的使用上很多c 的人員都是隨心而動。有用抽象類的純虛函式的,有直接用c型別的介面的。有乾脆提供介面類的 不一而足吧。根據實際情況,實事求是的選擇才是乙個好的標準。在c 中,大量...

跟我學c 中級篇 Linux下的動態庫之一

在前面將動態庫的知識初步學習了一下,本篇將著重講一下linux下的動態庫的編寫和使用。在gcck和 g 中,都提供了豐富的編譯選項,用來給程式設計師編譯動態加提供較多的選擇。可是,對於新手來說,如此多的編譯選項反而會讓其感覺到迷茫。所以還是那句話,先從簡單的入手,不要上去就啃大部頭,省得忙個昏天黑地...

跟我學C 中級篇 STL的學習

c 的標準庫主要包含兩大類,首先是包含c的標準庫的,當然,為了適應c 對一些c庫進行了少許的修改和增加。最重要的當然是物件導向的c 庫 而c 庫又可以分成兩大類,即物件導向的c 庫和標準模板庫,也就是題目中的stl。另外在此基礎上,還要提醒同學們的是,除了上面的庫,在各個平台的開發廠商中,還會針對實...