建立C語言靜態庫與動態庫

    「程序庫」就是包含了一些同音函數的數據和二進制可執行機器碼的文件。這些文件是目標文件的一種,其不能單獨執行。可是若是將其與其餘的可執行代碼結合起來就能夠執行。這些目標文件一般能夠完成同一類功能,他們能夠做爲其餘執行程序的一部分來執行。因爲庫的存在,使得用戶編寫的程序模塊化更強,從而能夠增強程序的再編譯,提升代碼的複用性。linux

從連接方式上,程序庫可分爲靜態庫和動態庫(共享庫)兩種:shell

  • 靜態庫:是在執行程序運行前就已經加入到執行碼中,成爲執行程序的一部分來執行。
  • 動態庫:是在執行程序啓動是加載到執行程序中,能夠被多個執行程序共享使用。

1、靜態庫

1.靜態庫的概念

靜態庫是一些目標代碼的集合。linux環境下的靜態庫目標文件通常以.a做爲擴展名。Linux環境下使用ar命令建立一個靜態庫。靜態庫的優勢在於使用簡單,編譯快速,靜態庫在應用程序生成時,已經編譯成爲可重定位的目標文件,所以可沒必要再編譯。windows

因爲靜態庫在編譯時已經複製到可執行代碼段中,因此不須要像使用動態庫那樣在程序加載時再次連接。bash

2.建立靜態庫

建立一個四則運算的靜態庫:模塊化

(1)四則運算的代碼爲:函數

/* 計算加法的函數 */
int add(int a, int b)
{
  return a + b;
}

/* 計算減法的運算 */
int sub(int a, int b)
{
  return a - b;
}

/* 計算乘法的運算 */
int mul(int a, int b)
{
  return a * b;
}

/* 計算除法的運算 */
int div(int a, int b)
{
  return a / b; 
}

(2)在shell中編譯源文件,生成一個可重定位的目標文件:工具

gcc -c static_lib.c

生成的目標文件爲:spa

static_lib.o

(3)Linux下使用工具ar建立一個靜態庫,或者將目標文件加入到一個已經存在的靜態庫中,使用方法以下:code

ar rcs 靜態庫名 目標文件1 目標文件2...目標文件n

該命令將目標文件1~n加入到指定的靜態庫中。若是該靜態庫不存在,則建立靜態庫文件。其中ar工具的參數rcs起到了重要的做用。這三個參數分別表示:索引

  • 參數r:把列表中的目標文件加入到靜態庫中
  • 參數c:若指定的靜態庫不存在,則建立該庫文件
  • 參數s:更新靜態庫文件的索引,是指包含新加入的目標文件的內容

如今使用剛生成的.o文件建立一個靜態庫:

ar rcs libstatic_lib.a static_lib.o

這樣就生成了一個新的靜態庫:

libstatic_lib.a

3.使用靜態庫

靜態庫建立成功後,須要連接到應用程序中使用。應用程序能夠引用該庫中的函數或者全局變量。爲了是應用程序能夠正確引用該庫中的全局符號,須要製做一個包含該靜態庫中全局符號聲明的頭文件,這個頭文件能夠包含在應用程序的頭文件中,這樣就可使用靜態庫中的全局符號了。

#include <stdio.h>
#include "static_lib.h"

int main(void)
{
  int a, b;
  printf("please input a and b\n");
  scanf("%d %d", &a, &b);
  printf("the add : %d\n", add(a, b));
  printf("the sub : %d\n", sub(a, b));
  printf("the mul : %d\n", mul(a, b));
  printf("the div : %d\n", div(a, b));
  return 0;
}

使用-l選項來指定靜態庫,-L參數來指定庫文件的搜索路徑。-l和-L以後都櫛jie風沐雨帶參數而不跟空格,因此用一下命令編譯:

gcc -L/home/daowm/WorkSpace/C/linux/ch7 static_main.c -lstatic_lib -o static_main

或者使用 "." 表示當前目錄:

gcc -L. static_main.c -lstatic_lib -o static_main

注意:-l是連接器選項,必定要放在被編譯的源文件以後,即上面的static_main.c以後,若放在前面則會連接失敗。

gcc也支持使用-static選項對靜態庫連接:

gcc static_main.c -static ./libstatic_lib.a -o static_main

以上三種方法均可以。

運行程序以下:

2、動態庫

1.動態庫的概念

動態庫又稱爲共享庫或者動態連接庫,現代程序中大量地使用動態連接庫,如windows下的dll文件和linux下的so文件,動態庫是在程序啓動時被裝載的。

當一個引用程序裝載了一個動態庫後,其餘應用程序仍能夠裝載同一個動態庫,這個被多個進程同時使用的動態庫在內存中只有一個副本。動態庫的優勢不少:

  • 是代碼
  • 便於程序發佈
  • 易於模塊更新,更新庫並不影響程序使用舊的版本
  • 在執行特定程序時,能夠覆蓋整個庫或者更新庫中的特定函數

2.建立動態庫

這裏使用上面的代碼來演示

(1)四則運算代碼

//static_lib.c
/* 計算加法的函數 */
int add(int a, int b)
{
  return a + b;
}

/* 計算減法的運算 */
int sub(int a, int b)
{
  return a - b;
}

/* 計算乘法的運算 */
int mul(int a, int b)
{
  return a * b;
}

/* 計算除法的運算 */
int div(int a, int b)
{
  return a / b; 
}

(2)Linux下使用gcc建立一個動態庫。因爲動態庫能夠被多個進程共享加載,因此須要生成位置無關的目標文件。這時須要使用gcc編譯器的-fPIC選項,該選項用於生成位置無關的代碼。除了須要使用-fPIC選項外,還須要使用-shared選項,該選項將位置無關的代碼製做爲動態庫。

gcc -shared -fPIC -o shared_lib.so static_lib.c

這時一個新的動態庫就建立成功了。以後用戶能夠在本身的應用程序中引用該庫中的函數,在程序加載的時候連接該庫就能夠了。

3.使用動態庫

動態庫建立成功後,應用程序能夠引用該庫中的函數或者全局變量。一樣在.h文件包含該動態庫中的全局符號:

//shared_lib.h

extern int add(int a, int b);  //加法函數的聲明
extern int sub(int a, int b);  //減法函數的聲明
extern int mul(int a, int b);  //乘法函數的聲明
extern int div(int a, int b);  //除法函數的聲明

編寫程序:

//shared_main.c

#include <stdio.h>
#include "shared_lib.h"

int main(void)
{
  int a, b;
  printf("please input a and b\n");
  scanf("%d %d", &a, &b);
  printf("the add : %d\n", add(a, b));
  printf("the sub : %d\n", sub(a, b));
  printf("the mul : %d\n", mul(a, b));
  printf("the div : %d\n", div(a, b));
  return 0;
}

使用動態庫編譯生成可執行程序:

gcc shared_main.c ./shared_lib.so -o shared_main

運行結果同上。

同時,另一個程序也可使用該動態庫,由於動態庫是共享的。

相關文章
相關標籤/搜索