


Linux靜態(tài)/動態(tài)鏈接庫的創(chuàng)建和使用
假設有下面幾個文件:
頭文件String.h,聲明相關函數(shù)原形,內(nèi)容如下:
Strlen.c:函數(shù)Strlen的實現(xiàn),獲取給定字符串的長度,內(nèi)容如下:
Strlnen.c:函數(shù)StrNlen的實現(xiàn),獲取給定字符串的長度,如果輸入字符串的長度大于指定的最大長度,則返回最大長度,否者返回字符串的實際長度,內(nèi)容如下:
生成靜態(tài)庫:
利用GCC生成對應目標文件:
gcc –c Strlen.c Strnlen.c
如果對應的文件沒有錯誤,gcc會對文件進行編譯生成Strlen.o和Strnlen.o兩個目標文件(相當于windows下的obj文件)。然后用ar創(chuàng)建一個名字為libstr.a的庫文件,并把Strlen.o 和Strnlen.o的內(nèi)容插入到對應的庫文件中。,相關命令如下:
ar –rc libstr.a Strlen.o Strnlen.o
命令執(zhí)行成功以后,對應的靜態(tài)庫libstr.a已經(jīng)成功生成。
/***********************************
Filename : String.h
Deion :
Author : HCJ
Date : 2006-5-7
************************************/
int Strlen(char *pStr);
int StrNlen(char *pStr, unsigned long ulMaxLen);
/**************************************
Filename : get string length
Deion :
Author : HCJ
Date : 2006/5/7
**************************************/
#include<stdio.h>
#include<assert.h>
int Strlen(char *pStr)
{
unsigned long ulLength;
assert(NULL != pStr);
ulLength = 0;
while(*pStr++)
{
ulLength++;
}
return ulLength;
}
**********************************************
Fileneme: mystrnlen.c
Deion: get input string length,if string large
max length input return max length,
else real length
Author: HCJ
Date : 2006-5-7
**********************************************/
#include<stdio.h>
#include<assert.h>
int StrNlen(char *pStr, unsigned long ulMaxLen)
{
unsigned long ulLength;
assert(NULL != pStr);
if(ulMaxLen <= 0)
{
printf("Wrong Max Length!\n");
return -1;
}
ulLength = 0;
while(*pStr++ && ulLength < ulMaxLen)
{
ulLength++;
}
return ulLength;
}
生成動態(tài)鏈接庫:
gcc -fpic -shared -o libstr.so Strlen.c Strnlen.c
-fpic 使輸出的對象模塊是按照可重定位地址方式生成的。
-shared指定把對應的源文件生成對應的動態(tài)鏈接庫文件libstr.so文件。
對應的鏈接庫已經(jīng)生成,下面看一下如何使用對應的鏈接庫。
靜態(tài)庫的使用:
假設有下面的文件要使用對應的的靜態(tài)庫:
編譯生成對應的目標文件:
gcc -c -I/home/hcj/xxxxxxxx main.c
生成可執(zhí)行文件:
gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.a
其中-I/home/hcj/xxxxxxxx和-L/home/hcj/xxxxxxxx是通過-I和-L指定對應的頭文件和庫文件的路徑。libstr.a是對應的靜態(tài)庫的名稱。這樣對應的靜態(tài)庫已經(jīng)編譯到對應的可執(zhí)行程序中。執(zhí)行對應的可執(zhí)行文件便可以對應得函數(shù)調(diào)用的結(jié)果。
/*****************************************
FileName: main.c
Deion: test static/dynamic library
Author: HCJ
Date : 2005-5-7
******************************************/
#include<stdio.h>
#include <String.h> //靜態(tài)庫對應函數(shù)的頭文件
int main(int argc, char* argv[])
{
char str[] = {"hello world"};
unsigned long ulLength = 0;
printf("The string is : %s\n", str);
ulLength = Strlen(str);
printf("The string length is : %d(use Strlen)\n", ulLength);
ulLength = StrNlen(str, 10);
printf("The string length is : %d(use StrNlen)\n", ulLength);
return 0;
}
動態(tài)庫的分為隱式調(diào)用和顯式調(diào)用兩種調(diào)用方法:
隱式調(diào)用的使用使用方法和靜態(tài)庫的調(diào)用差不多,具體方法如下:
gcc -c -I/home/hcj/xxxxxxxx main.c
gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.so //這里是*.so
在這種調(diào)用方式中,需要維護動態(tài)鏈接庫的配置文件/etc/ld.so.conf來讓動態(tài)鏈接庫為系統(tǒng)所使用,通常將動態(tài)鏈接庫所在目錄名追加到動態(tài)鏈接庫配置文件中。否則在執(zhí)行相關的可執(zhí)行文件的時候就會出現(xiàn)載入動態(tài)鏈接庫失敗的現(xiàn)象。在編譯所引用的動態(tài)庫時,可以在gcc采用 –l或-L選項或直接引用所需的動態(tài)鏈接庫方式進行編譯。在Linux里面,可以采用ldd命令來檢查程序依賴共享庫。
顯式調(diào)用:
/*****************************************
FileName: main2.c
Deion: test static/dynamic library
Author: HCJ
Date : 2005-5-7
******************************************/
#include<stdio.h>
#include<dlfcn.h>
int main(int argc, char* argv[])
{
//define function pointor
int (*pStrlenFun)(char* pStr); //聲明對應的函數(shù)的函數(shù)指針
int (*pStrnlenFun)(char* pStr, int ulMaxLen);
char str[] = {"hello world"};
unsigned long ulLength = 0;
void *pdlHandle;
char *pszErr;
pdlHandle = dlopen("./libstr.so", RTLD_LAZY); //加載鏈接庫/libstr.so
if(!pdlHandle)
{
printf("Failed load library\n");
}
pszErr = dlerror();
if(pszErr != NULL)
{
printf("%s\n", pszErr);
return 0;
}
//get function from lib
pStrlenFun = dlsym(pdlHandle, "Strlen"); //獲取函數(shù)的地址
pszErr = dlerror();
if(pszErr != NULL)
{
printf("%s\n", pszErr);
return 0;
}
pStrnlenFun = dlsym(pdlHandle, "StrNlen");
pszErr = dlerror();
if(pszErr != NULL)
{
printf("%s\n", pszErr);
return 0;
}
printf("The string is : %s\n", str);
ulLength = pStrlenFun(str); //調(diào)用相關的函數(shù)
printf("The string length is : %d(use Strlen)\n", ulLength);
ulLength = pStrnlenFun(str, 10);
printf("The string length is : %d(use StrNlen)\n", ulLength);
dlclose(pdlHandle);
return 0;
}
gcc -o mian2 -ldl main2.c
用gcc編譯對應的源文件生成可執(zhí)行文件,-ldl選項,表示生成的對象模塊需要使用共享庫。執(zhí)行對應得文件同樣可以得到正確的結(jié)果。
相關函數(shù)的說明如下:
(1)dlopen()
第一個參數(shù):指定共享庫的名稱,將會在下面位置查找指定的共享庫。
-環(huán)境變量LD_LIBRARY_PATH列出的用分號間隔的所有目錄。
-文件/etc/ld.so.cache中找到的庫的列表,用ldconfig維護。
-目錄usr/lib。
-目錄/lib。
-當前目錄。
第二個參數(shù):指定如何打開共享庫。
-RTLD_NOW:將共享庫中的所有函數(shù)加載到內(nèi)存
-RTLD_LAZY:會推后共享庫中的函數(shù)的加載操作,直到調(diào)用dlsym()時方加載某函數(shù)
(2)dlsym()
調(diào)用dlsym時,利用dlopen()返回的共享庫的phandle以及函數(shù)名稱作為參數(shù),返回要加載函數(shù)的入口地址。
(3)dlerror()
該函數(shù)用于檢查調(diào)用共享庫的相關函數(shù)出現(xiàn)的錯誤。
這樣我們就用簡單的例子說明了在Linux下靜態(tài)/動態(tài)庫的創(chuàng)建和使用。
關鍵字:鏈接庫、參數(shù)、函數(shù)、共享、加載
新文章:
- CentOS7下圖形配置網(wǎng)絡的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統(tǒng)后丟失windows啟動項
- CentOS單網(wǎng)卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網(wǎng)打印機IP講解
- CentOS7使用hostapd實現(xiàn)無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網(wǎng)絡重啟出錯
- 解決Centos7雙系統(tǒng)后丟失windows啟動項
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統(tǒng)有什么不同呢
- Centos 6.6默認iptable規(guī)則詳解