使用庫函數是源碼的一種保護??? <我猜的.>
庫函數其實不是新鮮的東西,我們一直都在用,比如C庫.
我們執行pringf() 這個函數的時候,就是調用C庫的函數.
下面記錄靜態庫和動態庫的生成和使用.
靜態庫:libxxx.a
動態庫:libxxx.so
靜態庫: 在程序編譯的時候,將庫編譯進可執行程序中, 運行的時候不需要外部函數庫
動態庫: 在程序運行的時候,將庫加載到程序中,運行的時候需要外部函數庫
函數庫的目錄有 /lib 和 /usr/lib 和 自定義
一. 靜態庫的生成和使用
下面通過一個簡單的小栗子來介紹庫函數怎么生成和使用.
1.庫函數的源碼 hello.c
#include "stdio.h"
int hello(void){ printf("hello lib"); return 0; }
2. 庫函數的頭文件 hello.h
#ifndef __HELLO_H #define __HELLO_H
int hello(void); #endif
庫文件的頭文件是庫文件的目錄,因為庫文件是保護的,看不到里面的源碼,所以把函數接口通過頭文件來讓人調用 .
這樣就實現了接口,也保護了源碼
3.編譯靜態庫函數
3.1 將 hello.c 編譯成目標文件 生成 hello.o文件
gcc -c hello.c
3.2 將.o文件打包成靜態庫 生成 libhello.a庫文件
ar -cr libhello.a hello.o
4 使用靜態庫,因為靜態庫是在編譯的時候一起打包進程序的,所以如果編譯的時候沒有靜態庫文件,則無法編譯
4.1 main.c 寫一個main函數來調用庫函數
#include "hello.h" //引入庫函數的頭文件,這樣才能找到函數聲明
int main{ hello(); //調用庫函數
}
正常編譯的時候是沒辦法通過的. 因為編譯器找不到 hello() 的實現代碼. 如圖:
所以在編譯的時候要加入庫引用
gcc -c main -L. -lhello -o a.out
-L<路徑> 引用自定義庫的路徑,如果調用系統庫就不用-L '.'表示當前文件夾
-lxxxx 這里libhello.a 只要寫hello 就可以 //小寫的L
4.2 直接可以執行,因為庫函數已經被編譯進去了
二.動態庫的編譯及使用
同樣的hello.c 源碼
1.生成.o文件
gcc -c -fpic hello.c //如果這里沒有加-fpic 下一步就會提示你重新用 -fpic編譯
2. 編譯成動態庫
gcc -shared -fpic -o libhello.so hello.o
-shared 是生成動態庫
-fpic 生成位置無關代碼,默認加
3. 使用動態庫 和靜態庫一樣
gcc main.c -L. -lhello -o a.out
4. 執行 用動態庫編譯的程序沒辦法直接執行
在讀取共享庫libhello.so的時候出錯,沒有找到該文件
因為動態庫程序會默認在 /lib 或者 /usr/lib的路徑下尋找, 所以
解決的辦法有3個:
1. 將.so 文件拷貝到 /usr/lib/文件夾下面
2.添加PATH環境變量
export LD_LIBRARY_PATH=<動態庫所在的絕對路徑>
3.修改配置腳本
將動態庫所在的路徑加到 /etc/ld.so.conf 文件里
vim /etc/ld.so.conf
添加后刷新
/sbin/ldconfig