日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux c 如何编译静态库,Linux C 编程入门之一:gcc 编译动态库和静态库

發布時間:2025/4/5 linux 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux c 如何编译静态库,Linux C 编程入门之一:gcc 编译动态库和静态库 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

主調用程序源代碼3-1:main.c

/**

* main.c

*/

#include

#include

#include "hello_fn.h"

int

main ()

{

hello("cheungmine");

printf("sqrt(2.0) = %f\n", sqrt(2.0));

return 0;

}

庫源代碼3-2:hello_fn.c

/**

* hello_fn.c

*/

#include

void hello(const char *msg)

{

printf("Hello %s!\n", msg);

}

庫頭文件源代碼3-3:hello_fn.h

/**

* hello_fn.h

*/

void hello(const char *msg);

2 編譯庫

2.1 首先編譯源文件生成對象(obj)文件(main.o, hello_fn.o):

$ gcc -W -Wall -ansi -pedantic -I. -c main.c

$ gcc -W -Wall -ansi -pedantic -I. -c hello_fn.c

2.2 然后從對象文件編譯動態庫文件(libhello.so)和靜態庫(libhello.a)

$ gcc -shared hello_fn.o -o libhello.so

或者直接從源代碼編譯:

$ gcc -shared -I. hello_fn.c -o libhello.so

編譯靜態庫相對簡單,就是相當于目標文件歸檔:

$ ar r libhello.a hello_fn.o

3 編譯使用庫的主程序

3.1 如果不鏈接庫的情況下編譯一個主程序是:

$ gcc main.o -o main

或者

$ gcc -c main.c -o main

但是由于我們在main.c的代碼中寫固定了調用庫的代碼(hello函數),所以,必須鏈接到這個庫才行。

3.2 鏈接到動態庫libhello.so

$ gcc main.o -o main ./libhello.so

這樣在當前目錄下就生成了:main.exe(我的cygwin環境,Linux環境下沒有擴展名)

運行這個main.exe:

$ ./main.exe

刪除libhello.so,再運行main.exe會報錯誤:error while loading shared libraries: libhello.so: cannot open shared object...

3.3 鏈接到靜態庫libhello.a

$ gcc main.o -o main2 ./libhello.a

刪除libhello.a,運行main2.exe,一切正常。說明程序的確鏈接到靜態庫了。

4 查看程序依賴的庫

$ file main.exe main2.exe

$ ldd main.exe main2.exe

如果我們的動態庫libhello.so與主程序不在同一個目錄下,怎么辦?

復制libhello.so和libhello.a到另外一個目錄,比如:/cygdrive/c/temp,那么編譯主程序為:

$ gcc main.o -o main /cygdrive/c/temp/libhello.so

執行:

$ export PATH=/cygdrive/c/temp:$PATH

$ ./main.exe

5 運行時加載動態庫

修改main.c文件為如下清單:

/**

* main.c

*/

#include

#include

#include

#include "hello_fn.h"

void dl_hello()

{

void *dp;

char *error;

void (*fn_hello)(const char*);

dp = dlopen("libhello.so", RTLD_LAZY );

if(!dp) {

printf("%s\n", dlerror());

exit(1);

}

fn_hello = dlsym(dp, "hello");

if(!fn_hello) {

printf("%s\n", dlerror());

exit(1);

}

fn_hello("cheungmine: load library when running");

dlclose(dp);

}

int

main ()

{

// hello("cheungmine");

dl_hello();

printf("sqrt(2.0) = %f\n", sqrt(2.0));

return 0;

}

然后重新編譯main.exe和libhello.so如下:

編譯源文件

$ gcc -Wall -I. -c main.c

$ gcc -Wall -I. -c hello_fn.c

編譯動態庫

$ gcc -shared hello_fn.o -o libhello.so

鏈接主程序,但不鏈接到動態庫。

$ gcc main.o -o main.exe

執行下面的代碼可以看到libhello.so并不在main.exe的依存之列:

$ ldd main.exe

移動庫到其他目錄,通過修改環境變量,程序main.exe執行正確:

$ mv libhello.so /cygdrive/c/temp

$ export PATH=.:/cygdrive/c/temp:$PATH

$ ./main.exe

6 總結

通過上面的練習,基本清楚了如何用gcc編譯程序,包括靜態鏈接庫和動態鏈接庫。通過下面的表格可以看到

Linux和Windows的區別:

Windows????????????????????? Unix/Linux

----------------------------------------------------------------------

靜態鏈接庫????????????? hello.lib?????????????????????? ? ?? libhello.a

動態鏈接庫????????????? hello.dll????????????????????? ? ??? libhello.so

延遲加載????????????????? LoadLibrary??????????????? ? ? dlopen

GetProcAddress??????????? dlsym

FreeLibrary ????? ? ????????? ? dlclose

本文全部內容在cygwin上運行的,和真實的Linux環境還是存在差異的。gcc版本3.4.4。

總結

以上是生活随笔為你收集整理的linux c 如何编译静态库,Linux C 编程入门之一:gcc 编译动态库和静态库的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。