1. 程式人生 > >c語言中靜態庫動態庫的建立與使用

c語言中靜態庫動態庫的建立與使用

在c程式中存在兩種庫檔案,分別為靜態庫檔案與動態庫檔案也叫共享庫檔案,系統的庫檔案存放路徑為 usr/lib目錄下:
靜態庫檔案就是一些.o目標檔案的集合,以.a結尾。
靜態庫在程式連結的時候使用,聯結器會將程式中使用到的函式的程式碼從庫檔案拷貝到可執行檔案中,一旦連結完成,
在程式執行的時候就不需要靜態庫了。
靜態庫的建立:

首先看一下原始檔

fun.c
#include <stdio.h>
int foo(char* ch)
{
	printf("foo: %s\n",ch);
	return 0;
}

fun.h
#ifndef _FUNC_
#define _FUNC_
#ifdef __cplusplus
extern "C" {  //告訴c++編譯此處使用gcc編譯
#endif
int foo(char* ch);
#ifdef __cplusplus
}
#endif
#endif

main.cpp
#include "fun.h"
#include <stdio.h>
#include <iostream>
using namespace::std;
int main()
{
	char* ch = "我是字串";
	foo(ch);
	cout << "lalalala" << endl;
	return 0;
}
若需要直接使用make編譯生成可執行檔案,則附上makefile檔案:
CC = gcc
CXX = g++
ADD_CFLAGS := -Wall -g

CFLAGS := $(ADD_CFLAGS) $(CFLAGS)
CPPFLAGS := $(ADD_CFLAGS)
LDFLAGS := $(LDFLAGS)

targets = test
.PHONY: all
all: $(targets)
test: main.o fun.o
	$(CXX) $^ -o [email protected] $(LDFLAGS)
main.o: main.cpp
	$(CXX) $(CPPFLAGS) -c $< -o 
[email protected]
fun.o: fun.c fun.h $(CC) $(CFLAGS) -c $< -o [email protected] .PHONY: clean clean: $(RM) $(targets) *.o
當前目錄下執行make即可編譯。

接下來看一下如何將fun.c編譯成庫檔案:

現在要將fun.c編譯成靜態庫,libmytest.a

1.將fun.c 和main.c 編譯成目標檔案,生成fun.o main.o
    gcc -o fun.o -c fun.c 
    g++ -o mian.o -c main.cpp

2.將fun.o編譯成靜態庫檔案,libmytest.a
    編譯命令為: ar rcs lib庫檔案.a 目標檔案1 目標檔案2 ...
    此處使用 ar rcs libmytest.a fun.o
    r:表示將.o的目標檔案加入到靜態庫中
  c:表示建立靜態庫
  s:表示生產索引
注意:生成庫檔案時建議在名字前加上字首lib,及lib庫檔名.a,否則後面連結時會出錯。

接下來要使用靜態庫:
編譯方式有兩種:
    g++ -o 可執行檔案 呼叫者的目標檔案(就是這裡的fun.o和main.o) -Ldir -l庫檔名(不加lib)
    g++ -o 可執行檔案 標頭檔案路徑 呼叫者的原始檔(就是這裡的main.c檔案) -Ldir -l庫檔名(不加lib)

現在開始編譯,生成可執行檔案test:
    g++ -o test main.o -L./ -lmytest
-Ldir 指的是靜態庫的連結路徑,由於我的就是在當前目錄下,直接寫./就可以了

執行./test

[email protected]:~$ ./test
foo: 我是字串
lalalala

當將靜態庫libmytest.a刪除後再次執行,依然可正常執行。

動態庫的建立與使用:
動態庫是指在程式連結的時候並不像靜態庫那樣拷貝使用函式中的程式碼,而只是做一些標記,在程式開始啟動(實際上在載入程式時)執行的時候,
載入所需的函式。

動態庫的建立:
原始檔還是fun.c fun.h main.c

第一步:首先還是先生成fun.o main.o目標檔案
第二步:使用gcc編譯
    gcc -shared -fPIC -o lib庫檔案.so 目標檔案1 目標檔案2 ...
編譯生成libmytest.so:
    gcc -shared -fPIC -o libmytest.so fun.o
若編譯出錯:/usr/bin/ld: fun.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
      fun.o: could not read symbols: Bad value collect2: ld returned 1 exit status
此原因是系統造成的,需要重新生成一下目標檔案,編譯命令如下:
gcc -o fun.o -c -fPIC fun.c
然後再執行gcc -shared -fPIC -o libmytest.so fun.o即可;

動態庫的使用(和靜態庫一樣):
    g++ -o 可執行檔案 呼叫者的目標檔案(就是這裡的fun.o和main.o) -Ldir -l庫檔名(不加lib)
    g++ -o 可執行檔案 標頭檔案路徑 呼叫者的原始檔(就是這裡的main.c檔案) -Ldir -l庫檔名(不加lib)

現在開始編譯,生成可執行檔案test:
    g++ -o test main.o -L./ -lmytest

執行./test
結果出錯:libmytest.so: cannot open shared object file: No such file or directory
需要手動配置一下路徑:
    第一種:cp libmytest.so /usr/lib
    第二種:export LD_LIBRARY_PATH=./
然後再次執行,OK

若刪除libmytest.so,執行./test將會出錯。

相關推薦

c語言靜態動態建立使用

在c程式中存在兩種庫檔案,分別為靜態庫檔案與動態庫檔案也叫共享庫檔案,系統的庫檔案存放路徑為 usr/lib目錄下: 靜態庫檔案就是一些.o目標檔案的集合,以.a結尾。 靜態庫在程式連結的時候使用,聯結器會將程式中使用到的函式的程式碼從庫檔案拷貝到可執行檔案中,一旦連結完成

linux c 語言程式設計環境:動態靜態的製作

庫: 庫用於將相似函式打包在一個單元中。然後這些單元就可為其他開發人員所共享,並因此有了模組化程式設計這種說法 — 即,從模組中構建程式。Linux 支援兩種型別的庫,每一種庫都有各自的優缺點。靜態庫包

c語言記憶體的動態分配釋放(多維動態陣列構建)

一. 靜態陣列與動態陣列    靜態陣列比較常見,陣列長度預先定義好,在整個程式中,一旦給定大小後就無法再改變長度,靜態陣列自己自動負責釋放佔用的記憶體。    動態陣列長度可以隨程式的需要而重新指定大小。動態陣列由記憶體分配函式(malloc)從堆(heap

常見演算法:C語言連結串列的操作(建立,插入,刪除,輸出)

連結串列中最簡單的一種是單向連結串列,它包含兩個域,一個資訊域和一個指標域。這個連結指向列表中的下一個節點,而最後一個節點則指向一個空值。 一個單向連結串列包含兩個值: 當前節點的值和一個指向下一個節點的連結 一個單向連結串列的節點被分成兩個部分。第一個部分儲存或者顯示關於

C語言靜態動態順序表的實現

      在學習了C語言之後,我們先來了解一下簡單的資料結構,順序表和連結串列。      順序表和連結串列都屬於線性資料結構。順序表的底層相當於一個數組,因為它的空間是一段地址連續的儲存單元;連結串列的底層不需要所有的空間都連續,只要通過指標就可以找到下一個儲存空間。下面

c語言靜態全域性變數、靜態區域性變數、全域性變數、區域性變數、巨集

全域性變數: 全域性變數具有全域性作用域。,它只編譯期被始化一次,它不能用變數來初始化。全域性變數只需要在一個原始檔中定義,就可以作用於所有的原始檔。在其他不包含全域性變數定義的原始檔中需要用extern關鍵詞來再次宣告這個全域性變數 區域性變數: 區域性變數只有區域性

C語言學習指標遇到的問題以後的學習道路

C語言中學習指標遇到的問題與以後的學習道路 在這個指標的學習裡,我學習的可謂是相當的掙扎了。 沒有了往日學習其它章節的高效性,有的只是無窮無盡的問題與懵懂。 他就像是一層迷霧,令我捉摸不透。 首先要注意的就是指標這個概念:它指的就是地址。沒其它任何含義 然後就是指標變數這個東西,不就是加

C語言變數和函式的宣告定義

一、變數在將變數前,先解釋一下宣告和定義這兩個概念。宣告一個變數意味著向編譯器描述變數的型別,但並不為變數分配儲存空間。定義一個變數意味著在宣告變數的同時還要為變數分配儲存空間。在定義一個變數的同時還可以對變數進行初始化。 區域性變數通常只定義不宣告,而全域性變數多在原始檔中定義,在標頭檔案中宣告。 區域性變

C語言指向字串常量的指標指向字串陣列的指標

char str[] = "1234567asdf";char*pstr = str;上面是定義了一個字串陣列及一個指向這個字串陣列的指標,可以通過這個指標對陣列中的內容進行操作;例如:*(pstr +

C語言字元陣列的初始化賦值

1.字元陣列初始化 在C語言中,字串是當做字元陣列來處理的;所以字串有兩種宣告方式,一種是字元陣列,一種是字元指標。 字元陣列初始化 char parr[] = "zifuchuanshuzu"; char charr[] = { 'z','i',

C語言呼叫靜態函式和動態函式的方式

C語言中呼叫動態庫函式的兩種方式 方式一.隱式呼叫 將動態庫的相關檔案拷貝到當前目錄下(lib、dll),然後新增以下程式碼,在程式中指定連線庫函式。 注意:第二個引數給出的是引入庫檔案(或稱“匯出庫檔案”),而不是dll。在程式執行過程中,lib將dll中需要用到的函式對映到對應的記憶

linux建立自己的靜態 動態並使用

庫依賴: gcc connect.c –o connect –I /usr/include/mysql –L /usr/lib/mysql -lmysqlclient//-I是找到自己寫的標頭檔案所在的位置 -L是找到自己所寫的動態庫所在的位置,並且寫上函式名,靜態庫不用寫-L,只寫函式名//-I 是i 的大

簡談用g++編譯執行c++程式碼流程,以及動態靜態建立使用

一 g++ 編譯執行hello world 1編寫hello world 程式碼 #include<iostream> using namespace std; int main() { cout << "hello

c語言生成靜態.a和動態.so

在windows下動態連結庫是以.dll字尾的檔案,二在Linux中,是以.so作字尾的檔案。 動態連結庫的好處就是節省記憶體空間。 1、Linux下建立動態連結庫 在使用GCC編譯程式時,只需加上-shared選項即可,這樣生成的執行程式即為動態連結庫。 例如有檔案:he

sqlite學習筆記7:C語言使用sqlite之打開數據

實例 clas details code 返回 pri san filename stdlib.h 數據庫的基本內容前面都已經說得差點兒相同了。接下看看如何在C語言中使用sqlite。 一 接口 sqlite3_open(const char *filename, s

C語言文件的加載方式

部分函數 HA 靜態 區分 最大 靜態鏈接 open 返回函數 接收 Linux下使用庫有三種方式,靜態鏈接庫,動態鏈接庫和動態加載庫。 -靜態鏈接庫: 在編譯過程中,將所需要的庫文件生成a文件並直接鏈接到最終的可執行文件當中,所以相對來講,靜態方式生成的image大小最

『Python CoolBook』C擴展_其六_從C語言調用Python代碼

callable 什麽 跟著 來講 cpp iat mst 轉化 gcc 一、C語言運行pyfun的PyObject對象 思路是在C語言中提供實參,傳給python函數: 獲取py函數對象(PyObject),函數參數(C類型) 獲取GIL(PyGILState_

(轉載)C語言常用的幾個標頭檔案及函式 (stdio.h ,string.h ,math.h ,stdlib.h)

不完全統計,C語言標準庫中的標頭檔案有15個之多,所以我主要介紹常用的這四個標頭檔案stdio.h ,string.h ,math.h ,stdlib.h ,以後用到其他的再做補充。下面上乾貨: 1.<stdio.h>:定義了輸入輸出函式、型別以及巨集,函式

Ubuntu--(5)Linux下C++編譯生成自定義靜態/動態

編譯生成靜態庫: 1.編寫CPP檔案test.h #include <iostream> using namespace std; class ADD_SUB{ public

C語言函式自帶的排序函式qsort

之前一直不知道C語言還有預設的排序函式,而且還是快速排序的函式,當時覺得自己C語言白學了,瞭解之後我覺得應該把這個函式的用法和用例展示出來,供大家參考。 #include <stdlib.h> void qsort( void *buf, size_t num,