from : http://hi.baidu.com/xiaochongs/blog/item/23a70b5592e662c4b645aef2.html

Windows系統(tǒng)一樣Linux也有靜態(tài)/動態(tài)鏈接庫,下面介紹創(chuàng)建和使用方法: 
   

假設(shè)有下面幾個文件: 
頭文件String.h,聲明相關(guān)函數(shù)原形,內(nèi)容如下: 
Strlen.c
:函數(shù)Strlen的實現(xiàn),獲取給定字符串的長度,內(nèi)容如下: 
Strlnen.c
:函數(shù)StrNlen的實現(xiàn),獲取給定字符串的長度,如果輸入字符串的長度大于指定的最大長度,則返回最大長度,否者返回字符串的實際長度,內(nèi)容如下: 
生成靜態(tài)庫: 
 
利用GCC生成對應(yīng)目標(biāo)文件: 
gcc –c Strlen.c Strnlen.c 
如果對應(yīng)的文件沒有錯誤,gcc會對文件進(jìn)行編譯生成Strlen.oStrnlen.o兩個目標(biāo)文件(相當(dāng)于windows下的obj文件)。然后用ar創(chuàng)建一個名字為libstr.a的庫文件,并把Strlen.o Strnlen.o的內(nèi)容插入到對應(yīng)的庫文件中。,相關(guān)命令如下: 
ar –rc libstr.a Strlen.o Strnlen.o 
命令執(zhí)行成功以后,對應(yīng)的靜態(tài)庫libstr.a已經(jīng)成功生成。 

/*********************************** 
Filename : String.h 
Description : 
Author   : HCJ 
Date     : 2006-5-7 
************************************/ 

int Strlen(char *pStr); 
int StrNlen(char *pStr, unsigned long ulMaxLen); 



/************************************** 
Filename    : get string length 
Description  :  
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 
Description: 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
指定把對應(yīng)的源文件生成對應(yīng)的動態(tài)鏈接庫文件libstr.so文件。 
對應(yīng)的鏈接庫已經(jīng)生成,下面看一下如何使用對應(yīng)的鏈接庫。 
靜態(tài)庫的使用: 
假設(shè)有下面的文件要使用對應(yīng)的的靜態(tài)庫
編譯生成對應(yīng)的目標(biāo)文件: 
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指定對應(yīng)的頭文件和庫文件的路徑。libstr.a是對應(yīng)的靜態(tài)庫的名稱。這樣對應(yīng)的靜態(tài)庫已經(jīng)編譯到對應(yīng)的可執(zhí)行程序中。執(zhí)行對應(yīng)的可執(zhí)行文件便可以對應(yīng)得函數(shù)調(diào)用的結(jié)果。 

/***************************************** 
FileName: main.c 
Description: test static/dynamic library 
Author: HCJ 
Date  : 2005-5-7 
******************************************/ 
#include<stdio.h> 
#include <String.h>   //
靜態(tài)庫對應(yīng)函數(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)用方式中,需要維護(hù)動態(tài)鏈接庫的配置文件/etc/ld.so.conf來讓動態(tài)鏈接庫為系統(tǒng)所使用,通常將動態(tài)鏈接庫所在目錄名追加到動態(tài)鏈接庫配置文件中。否則在執(zhí)行相關(guān)的可執(zhí)行文件的時候就會出現(xiàn)載入動態(tài)鏈接庫失敗的現(xiàn)象。在編譯所引用的動態(tài)庫時,可以在gcc采用 –l-L選項或直接引用所需的動態(tài)鏈接庫方式進(jìn)行編譯。在Linux里面,可以采用ldd命令來檢查程序依賴共享庫。 
顯式調(diào)用: 

/***************************************** 
FileName: main2.c 
Description: 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);     //
聲明對應(yīng)的函數(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)用相關(guān)的函數(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編譯對應(yīng)的源文件生成可執(zhí)行文件,-ldl選項,表示生成的對象模塊需要使用共享庫。執(zhí)行對應(yīng)得文件同樣可以得到正確的結(jié)果。 
相關(guān)函數(shù)的說明如下: 
(1)dlopen() 
第一個參數(shù):指定共享庫的名稱,將會在下面位置查找指定的共享庫。 
-環(huán)境變量LD_LIBRARY_PATH列出的用分號間隔的所有目錄。 
-文件/etc/ld.so.cache中找到的庫的列表,用ldconfig維護(hù)。 
-目錄usr/lib 
-目錄/lib 
-當(dāng)前目錄。 
第二個參數(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)用共享庫的相關(guān)函數(shù)出現(xiàn)的錯誤。 
 
這樣我們就用簡單的例子說明了在Linux下靜態(tài)/動態(tài)庫的創(chuàng)建和使用。