導航:首頁 > 源碼編譯 > 調用動態庫的函數怎麼被編譯的

調用動態庫的函數怎麼被編譯的

發布時間:2023-05-14 16:58:21

A. 動態庫鏈接編譯

這里的動態的意思應該是模塊代碼是動態載入的
而不是隨著應用程序一起編譯
只要動態庫里的函數介面不變
應用程序就無需重新編譯
只需將動態庫重新編譯後替換掉舊的動態庫即可
如果動態庫的函數介面有變動
那麼應用程序就要重新編譯發布
這也是我的個人理解~~~

B. 靜態庫和動態庫的區別以及使用

我們通常把一些公用函數製作成函數庫,供其它程序使用。

函數庫分為靜態庫和動態庫兩種。

靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態庫。

動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態庫存在。

本文主要通過舉例來說明在linux中如何創建靜態庫和動態庫,以及使用它們。

在創建函數庫前,我們先來准備舉例用的源程序,並將函數庫的源程序編譯成.o文件。

第1步:編輯得到舉例的程序--hello.h、hello.c和main.c;

hello.h(見程序1)為該函數庫的頭文件。

hello.c(見程序2)是函數庫的源程序,其中包含公用函數hello,該函數將在屏幕上輸出"Hello XXX!"。

main.c(見程序3)為測試庫文件的主程序,在主程序中調用了公用函數hello。

程序1: hello.h

#ifndef HELLO_H

#define HELLO_H

void hello(const char *name);

#endif //HELLO_H

程序2: hello.c

#include

void hello(const char *name)

{

printf("Hello %s!/n", name);

}

程序3: main.c

#include "hello.h"

int main()

{

hello("everyone");

return 0;

}

第2步:將hello.c編譯成.o文件;

無論靜態庫,還是動態庫,都是由.o文件創建的。因此,我們必須將源程序hello.c通過gcc先編譯成.o文件。

在系統提示符下鍵入以下命令得到hello.o文件。

# gcc -c hello.c

#

(注1:本文不介紹各命令使用和其參數功能,若希望詳細了解它們,請參考其他文檔。)

(注2:首字元"#"是系統提示符,不需要鍵入,下文相同。)

我們運行ls命令看看是否生存了hello.o文件。

# ls

hello.c hello.h hello.o main.c

#

(注3:首字元不是"#"為系統運行結果,下文相同。)

在ls命令結果中,我們看到了hello.o文件,本步操作完成。

下面我們先來看看如何創建靜態庫,以及使用它。

第3步:由.o文件創建靜態庫;

靜態庫文件名的命名規范是以lib為前綴,緊接著跟靜態庫名,擴展名為.a。例如:我們將創建的靜態庫名為myhello,則靜態庫文件名就是libmyhello.a。在創建和使用靜態庫時,需要注意這點。創建靜態庫用ar命令。

在系統提示符下鍵入以下命令將創建靜態庫文件libmyhello.a。

# ar cr libmyhello.a hello.o

#

我們同樣運行ls命令查看結果:

# ls

hello.c hello.h hello.o libmyhello.a main.c

#

ls命令結果中有libmyhello.a。

第4步:在程序中使用靜態庫;

靜態庫製作完了,如何使用它內部的函數呢?只需要在使用到這些公用函數的源程序中包含這些公用函數的原型聲明,然後在用gcc命令生成目標文件時指明靜態庫名,gcc將猛鍵會從靜態庫中將公用函數連接到目標文件中。注運知廳意,gcc會在靜態庫名前加上前綴lib,然後追加擴旁隱展名.a得到的靜態庫文件名來查找靜態庫文件。

在程序3:main.c中,我們包含了靜態庫的頭文件hello.h,然後在主程序main中直接調用公用函數hello。下面先生成目標程序hello,然後運行hello程序看看結果如何。

# gcc -o hello main.c -L. -lmyhello

# ./hello

Hello everyone!

#

我們刪除靜態庫文件試試公用函數hello是否真的連接到目標文件 hello中了。

# rm libmyhello.a

rm: remove regular file `libmyhello.a'? y

# ./hello

Hello everyone!

#

程序照常運行,靜態庫中的公用函數已經連接到目標文件中了。

我們繼續看看如何在Linux中創建動態庫。我們還是從.o文件開始。

第5步:由.o文件創建動態庫文件;

動態庫文件名命名規范和靜態庫文件名命名規范類似,也是在動態庫名增加前綴lib,但其文件擴展名為.so。例如:我們將創建的動態庫名為myhello,則動態庫文件名就是libmyhello.so。用gcc來創建動態庫。

在系統提示符下鍵入以下命令得到動態庫文件libmyhello.so。

# gcc -shared -fPCI -o libmyhello.so hello.o

#

我們照樣使用ls命令看看動態庫文件是否生成。

# ls

hello.c hello.h hello.o libmyhello.so main.c

#

第6步:在程序中使用動態庫;

在程序中使用動態庫和使用靜態庫完全一樣,也是在使用到這些公用函數的源程序中包含這些公用函數的原型聲明,然後在用gcc命令生成目標文件時指明動態庫名進行編譯。我們先運行gcc命令生成目標文件,再運行它看看結果。

# gcc -o hello main.c -L. -lmyhello

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

#

哦!出錯了。快看看錯誤提示,原來是找不到動態庫文件libmyhello.so。程序在運行時,會在/usr/lib和/lib等目錄中查找需要的動態庫文件。若找到,則載入動態庫,否則將提示類似上述錯誤而終止程序運行。我們將文件 libmyhello.so復制到目錄/usr/lib中,再試試。

# mv libmyhello.so /usr/lib

# ./hello

Hello everyone!

#

成功了。這也進一步說明了動態庫在程序運行時是需要的。

我們回過頭看看,發現使用靜態庫和使用動態庫編譯成目標程序使用的gcc命令完全一樣,那當靜態庫和動態庫同名時,gcc命令會使用哪個庫文件呢?抱著對問題必究到底的心情,來試試看。

先刪除 除.c和.h外的 所有文件,恢復成我們剛剛編輯完舉常式序狀態。

# rm -f hello hello.o /usr/lib/libmyhello.so

# ls

hello.c hello.h main.c

#

在來創建靜態庫文件libmyhello.a和動態庫文件libmyhello.so。

# gcc -c hello.c

# ar cr libmyhello.a hello.o

# gcc -shared -fPCI -o libmyhello.so hello.o

# ls

hello.c hello.h hello.o libmyhello.a libmyhello.so main.c

#

通過上述最後一條ls命令,可以發現靜態庫文件libmyhello.a和動態庫文件libmyhello.so都已經生成,並都在當前目錄中。然後,我們運行gcc命令來使用函數庫myhello生成目標文件hello,並運行程序 hello。

# gcc -o hello main.c -L. -lmyhello

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

#

從程序hello運行的結果中很容易知道,當靜態庫和動態庫同名時, gcc命令將優先使用動態庫。

C. linux 靜態庫和動態庫編譯的區別

Linux庫有動態與靜態兩種,動態通常用.so為後綴,靜態用.a為後綴。例如:libhello.so libhello.a
為了在同一系統中使用不同版本的庫,可以在庫文件名後加上版本號為後綴,例如: libhello.so.1.0,由於程序連接默認以.so為文件後綴名。所以為了使用這些庫,通常使用建立符號連接的方式。
ln -s libhello.so.1.0 libhello.so.1
ln -s libhello.so.1 libhello.so

動態庫和靜態庫的區別:
當要使用靜態的程序庫時,連接器會找出程序所需的函數,然後將它們拷貝到執行文件,由於這種拷貝是完整的,所以一旦連接成功,靜態程序庫也就不再需要了。然而,對動態庫而言,就不是這樣。動態庫會在執行程序內留下一個標記『指明當程序執行時,首先必須載入這個庫。由於動態庫節省空間,linux下進行連接的預設操作是首先連接動態庫,也就是說,如果同時存在靜態和動態庫,不特別指定的話,將與動態庫相連接。

兩種庫的編譯產生方法:
第一步要把源代碼編繹成目標代碼。以下面的代碼hello.c為例,生成hello庫:

/* hello.c */
#include
void sayhello()
{
printf("hello,world\n");
}
用gcc編繹該文件,在編繹時可以使用任何全法的編繹參數,例如-g加入調試代碼等:
gcc -c hello.c -o hello.o
1.連接成靜態庫
連接成靜態庫使用ar命令,其實ar是archive的意思
$ar cqs libhello.a hello.o
2.連接成動態庫
生成動態庫用gcc來完成,由於可能存在多個版本,因此通常指定版本號:
$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o
另外再建立兩個符號連接:
$ln -s libhello.so.1.0 libhello.so.1
$ln -s libhello.so.1 libhello.so
這樣一個libhello的動態連接庫就生成了。最重要的是傳gcc -shared 參數使其生成是動態庫而不是普通執行程序。
-Wl 表示後面的參數也就是-soname,libhello.so.1直接傳給連接器ld進行處理。實際上,每一個庫都有一個soname,當連接器發現它正在查找的程序庫中有這樣一個名稱,連接器便會將soname嵌入連結中的二進制文件內,而不是它正在運行的實際文件名,在程序執行期間,程序會查找擁有 soname名字的文件,%B

D. android已有動態庫怎麼編譯靜態庫

在eclipse工程目錄下建立一空碼個jni的文件夾
在jni文件夾中建立Android.mk和Application.mk文件

Android.mk文件:

Android提供的一種makefile文件,用來指定諸如編譯生成so庫名、引用的頭文件目錄、需要編賣凱譯的.c/.cpp文件和.a靜態庫文件等。詳見附件中的Android.mk。

Application.mk文件:

定義了項目的一些細節,比如APP_ABI := x86(編譯X86平台庫)、APP_PLATFORM := android-9(使用android-9以上的平台庫)。

NDK 編譯和使用靜態庫、動態庫
情況一:編譯靜態庫
情況二:編譯動態庫
情況三:編譯動態庫+靜態庫
情況四:已有第三方靜態庫(動態庫),編譯靜態庫(動態庫)

默認所有代碼和文件在$project/jni下,否則特殊說明。
情況一:編譯靜態庫
文件Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_STATIC_LIBRARY)

文件Application.mk:
APP_MODULES :=hello-jni

情況二:編譯動態庫
文件Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
情況三:編譯動態庫+靜態庫
文件Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylib_static
LOCAL_SRC_FILES := src.c
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := mylib_shared
LOCAL_SRC_FILES := src2.c
LOCAL_STATIC_LIBRARIES := mylib_static
include $(BUILD_SHARED_LIBRARY)
情況四:已有第三方靜態庫(動態庫),編譯靜態庫(動態庫)
文件Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := thirdlib1 # name it whatever
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libthird1.a # or $(so_path)/libthird1.so
#LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY) #or PREBUILT_SHARED_LIBRARY
include $(CLEAR_VARS)
LOCAL_MODULE := mylib_use_thirdlib
LOCAL_SRC_FILES := src.c
LOCAL_STATIC_LIBRARIES := thirdlib1 #or LOCAL_SHARED_LIBRARY

include $(BUILD_SHARED_LIBRARY) #如果編譯靜態庫,需要Application.mk
用cd命令移至jni目錄,運行/mnt/500G/public/NDK/android-ndk-r7b/ndk-build命令,這時命令行中可能會出現編譯錯誤,比如頭文件找不到,函數找不到等等,細心找找就能改掉。
編譯成功後,在工中虧喚程目錄下libs/x86中就會生成你想要的.so庫。

E. 請教關於linux中靜態庫與動態庫的問題

哈哈,簡單的來說可以按你這么理解,靜態庫就是在打包在程序裡面的,而動態庫是和程序分離開的,是程序需要的時候動態裝配進內存的。

說一下我自己的理解和經驗吧:動態庫之所以會用到,是因為有些庫會被多個程序用到,拿windows的例子來說吧,比方說你開兩個游戲,一個魔獸,一個極品飛車,這兩個都要用到activex 這個庫,如果做為動態庫,兩個程序共用一個,但是靜態庫就要分別為兩個游戲都生成庫,如果更多的話,這樣就浪費了內存很多空間。

靜態庫是和程序一起裝入內存的(其實靜態庫已經成為程序的一部分),而動態庫是動態裝入內存的,如果內存不大,又使用靜態庫,必然會發生很多的缺頁中斷,這樣效率會很低哦,你有興趣可以多多研究一下內存的一些演算法,linux kernel有現成的分頁演算法,會對你很有幫助的。

如果缺頁中斷不太明白的話可以看看操作系統的書,或者追問我,大家一起切磋交流~

F. VC程序調用動態庫,編譯時候也跟著編譯動態庫

不太清楚你的工程是如何建立的,想必一個工程是生成動態鏈接庫,另一個是調用程序EXE了。由於VC動態庫有兩種形式,Regular和Extended兩種,其中一種能導出類,另一種只能導出變數和函數。如果導出的是類,你在編譯EXE文件時自然需要用到類得聲明文件,即你前面所說的動態庫本身所引用的文件。如果導出的是函數或變數,有可能出現的情況是:一般為了代碼的重用性,把需要導出的函數或變數單獨放在一個頭文件中,用一個宏控制其導入、導出。編譯動態庫時,宏定義為導出,編譯EXE時,宏變為導入,這個頭文件為兩者共用。如果不小心在這個頭文件中包含了其他頭文件,也可能出現你說的情況。如果動態庫調用直接採用函數入口地址的方法,則什麼都不用聲明,當然,只適用於導出函數與變數的情形。

G. unix 下的C++編程在編譯時怎麼鏈接動態庫第二個問題 在程序中怎麼調用

你說的是手動顯示調用,不是靜態隱式調用。

#include<dlfcn.h>
此頭文件在編譯時需要加入 -ldl選項
動態鏈接庫 必須加入:-fpic選項。

------
void *dll=NULL;//保存動態鏈接庫的句柄。
int (*dll_fun)(char*)=NULL;//想要調用的函數指針。
dll=dlopen("/lib/XXX.so", RTLD_NOW)//打開so文件。
dll_fun=dlsym(dll,"my_print");//獲取指定函數的指針。
dll_fun("Call my_print");
dlclose(dll)
---
編譯鏈接有兩種方法,
1. 使用-lXX 選項,gcc會自動在庫路徑中鏈接libXX.so的文件 gcc main.c -lstdc++ -omain
2. 在命令行中將庫路徑作為參數傳入。 gcc main.c /lib/libstdc++.so -omain

H. C語言編寫的動態庫中的函數,如何才能被C++調用

有對應的靜態庫嗎?

有的話,加入項目編譯,然後把動態庫放到運行的地方就可漏余核以了。

如果沒有的話,就需要編寫代碼返掘調用毀猜了。

這里有篇比較好的文章
http://www.cnblogs.com/lhbssc/archive/2012/02/08/2342853.html

I. linux c++動態庫 調用 c動態庫函數

先把.cpp編譯成動態庫,編譯方梁坦或法:
g++ *.cpp –fPIC –shared –o libtest.so -libyourclib.so
其中,*.cpp表示你的.cpp文件,你可以把它們一一列出,
–fPIC:表示編譯為位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的,所以動態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。
–shared:指明編譯成動態庫。
libtest.so即為生成的動態庫,以lib開頭,方便後面使用
-libyourclib.so 是你的c動態庫名

編譯好之後,就可以信扮來編譯你的測試程序了:
gcc test.c -o test -ltest
其中,test是生成的可執橡伍行程序
-ltest表示引用生成的動態庫libtest.so
大概過程就是這樣,你先試一試

J. 請教關於android linux動態庫.so的載入調用

1、 .so動態庫的生成
可使用gcc或者g++編譯器生成動態庫文件(此處以g++編譯器為例)
g++ -shared -fPIC -c XXX.cpp
g++ -shared -fPIC -o XXX.so XXX.o
2、 .so動態庫的動態調用介面函數說明
動態庫的調用關系可以在需要調用動態庫的程序編譯時,通過g++的-L和-l命令來指定。例如:程序test啟動時需要載入目錄/root/src/lib中的libtest_so1.so動態庫,編譯命令可照如下編寫執行:
g++ -g -o test test.cpp –L/root/src/lib –ltest_so1
(此處,我們重點講解動態庫的動態調用的方法,關於靜態的通過g++編譯命令調用的方式不作詳細講解,具體相關內容可上網查詢)

Linux下,提供專門的一組API用於完成打開動態庫,查找符號,處理出錯,關閉動態庫等功能。
下面對這些介面函數逐一介紹(調用這些介面時,需引用頭文件#include <dlfcn.h>):
1) dlopen
函數原型:void *dlopen(const char *libname,int flag);
功能描述:dlopen必須在dlerror,dlsym和dlclose之前調用,表示要將庫裝載到內存,准備使用。如果要裝載的庫依賴於其它庫,必須首先裝載依賴庫。如果dlopen操作失敗,返回NULL值;如果庫已經被裝載過,則dlopen會返回同樣的句柄。
參數中的libname一般是庫的全路徑,這樣dlopen會直接裝載該文件;如果只是指定了庫名稱,在dlopen會按照下面的機制去搜尋:
a.根據環境變數LD_LIBRARY_PATH查找
b.根據/etc/ld.so.cache查找
c.查找依次在/lib和/usr/lib目錄查找。
flag參數表示處理未定義函數的方式,可以使用RTLD_LAZY或RTLD_NOW。RTLD_LAZY表示暫時不去處理未定義函數,先把庫裝載到內存,等用到沒定義的函數再說;RTLD_NOW表示馬上檢查是否存在未定義的函數,若存在,則dlopen以失敗告終。
2) dlerror
函數原型:char *dlerror(void);
功能描述:dlerror可以獲得最近一次dlopen,dlsym或dlclose操作的錯誤信息,返回NULL表示無錯誤。dlerror在返回錯誤信息的同時,也會清除錯誤信息。
3) dlsym
函數原型:void *dlsym(void *handle,const char *symbol);
功能描述:在dlopen之後,庫被裝載到內存。dlsym可以獲得指定函數(symbol)在內存中的位置(指針)。如果找不到指定函數,則dlsym會返回NULL值。但判斷函數是否存在最好的方法是使用dlerror函數,
4) dlclose
函數原型:int dlclose(void *);
功能描述:將已經裝載的庫句柄減一,如果句柄減至零,則該庫會被卸載。如果存在析構函數,則在dlclose之後,析構函數會被調用。
3、 普通函數的調用
此處以源碼實例說明。各源碼文件關系如下:
test_so1.h和test_so1.cpp生成test_so1.so動態庫。
test_so2.h和test_so2.cpp生成test_so2.so動態庫。
test_dl.cpp生成test_dl可執行程序,test_dl通過dlopen系列等API函數,並使用函數指針以到達動態調用不同so庫中test函數的目的。

閱讀全文

與調用動態庫的函數怎麼被編譯的相關的資料

熱點內容
軟通動力程序員節2021 瀏覽:845
安卓系統如何卸載安裝包 瀏覽:870
簡訊刪除助手文件夾 瀏覽:688
java辦公自動化 瀏覽:340
php中超鏈接 瀏覽:253
linux默認路由設置 瀏覽:36
linux如何掛載iso 瀏覽:432
vs程序換文件夾後不能編譯 瀏覽:557
安卓源碼編譯輸入腳本沒反應 瀏覽:47
phpmysql自增 瀏覽:167
把ppt保存為pdf 瀏覽:533
汽車密封件加密配件 瀏覽:887
黑馬程序員15天基礎班 瀏覽:560
java調整格式 瀏覽:521
香港雲伺服器租用價 瀏覽:78
linuxsublime3 瀏覽:560
imac混合硬碟命令 瀏覽:278
沈陽用什麼app租房車 瀏覽:857
00後高中生都用什麼app 瀏覽:239
戴爾塔式伺服器怎麼打開獨立顯卡 瀏覽:808