1. 程式人生 > >靜態庫連結動態庫時,如何使用該靜態庫

靜態庫連結動態庫時,如何使用該靜態庫

網上有各種靜態庫的建立&使用的例子,但都是超級簡單的例子,比如,靜態庫,就直接來個printf(),就完事了!
其實,實際使用時,靜態庫會複雜很多,比如會呼叫很多其他的動態庫。
下圖就是個例子:
這裡寫圖片描述

假設libXXX.a用了libpthread.so的函式“pthread_create”,那libXXX.a在連結時,有沒有把“pthread_create”函式copy到自己身上,使其完全獨立?main.c在連結時,只需要連結libXXX.a,還是連libpthread.so也要連結?!這就是我要討論的內容!

為了證實問題,我們寫個測試程式吧。一個是libXXX.a,一個是main.c。

1 靜態庫檔案libXXX.a原始碼

static_lib_example.h

//static_lib_example.h
#ifndef STATIC_LIB_EXAMPLE_H_INCLUDED
#define STATIC_LIB_EXAMPLE_H_INCLUDED

int testFunc(int x);

#endif

static_lib_example.c

//static_lib_example.c
#include "static_lib_example.h"
#include <stdio.h>
#include <pthread.h>
/* this function is run by the second thread */ void *thread_exe(void *x_void_ptr) { /* increment x to 100 */ int *x_ptr = (int *)x_void_ptr; while(++(*x_ptr) < 100); printf("x increment finished\n"); return NULL; } int testFunc(int x) { printf(" testFunc %i\n",x); pthread_t inc_x_thread; int
y; /* create a second thread which executes thread_exe(&y) */ if(pthread_create(&inc_x_thread, NULL, thread_exe, &y)) { fprintf(stderr, "Error creating thread\n"); return 1; } return 0; }

一個頭檔案,一個原檔案,很簡單。
好吧,然後得來個Makefile

#chenxf make file
#some notice
#target: prerequisites - the rule head
#[email protected] - means the target
#$^ - means all prerequisites
#$< - means just the first prerequisite

OUT_LIB = libstatic_lib_example.a

LIB_SRC := static_lib_example.c

TEMP_O := static_lib_example.o

$(TEMP_O): $(LIB_SRC)
        @gcc -c -o [email protected] $^

all:  $(OUT_LIB)

$(OUT_LIB): $(TEMP_O)
        @ar rcs [email protected] $^
clean:
        @rm -r *.a *.o

其實Makefile相當於2句命令。所以你不寫Makefile,敲下面2句command也行。

gcc -c static_lib_example.c -o static_lib_example.o

ar rcs libstatic_lib_example.a static_lib_example.o

好了,編譯結果如下:

ls

libstatic_lib_example.a Makefile static_lib_example.c static_lib_example.h static_lib_example.o

2. 呼叫靜態庫的程式main.c原始碼

我們就寫一個main.c,它會連結libstatic_lib_example.a,並呼叫函式testFunc(int x)

//main.c
#include "static_lib_example.h"
int main(int argc, char* argv[])
{
    testFunc(100);
    return 1;
}

3 編譯main.c的情況分析

編譯main.c(只需要一個命令,就不寫Makefile啦)

gcc -g -O3 -Wall main.c -o main -I/home/chenxf/static_lib_sample/ -L/home/chenxf/static_lib_sample/ -lstatic_lib_example

-I表示標頭檔案的路徑
-L表示庫的路徑,即libstatic_lib_example.a的路徑。

上面的命令,表示main程式,只連結靜態庫libXXX.a。(好吧,就是libstatic_lib_example.a啦,幹嘛這麼糾結名字!^^)

編譯結果

/home/chenxf/static_lib_sample/libstatic_lib_example.a(static_lib_example.o):在函式‘testFunc’中:
static_lib_example.c:(.text+0x86):對‘pthread_create’未定義的引用
static_lib_example.c:(.text+0xd4):對‘pthread_join’未定義的引用
collect2: error: ld returned 1 exit status

出錯啦!!!!!!
在main.c連結的時候,說找不到pthread_create了!

看來,靜態庫libXXX.a並沒有把動態庫的函式copy到自己身上,只留了符號表,所以main.c要用libXXX.a時,還必須連結動態庫libpthread.so。也就是

gcc -g -O3 -Wall main.c -o main -I/home/chenxf/static_lib_sample/ -L/home/chenxf/static_lib_sample/ -static -lstatic_lib_example -lpthread

(libpthread.so在預設的系統庫目錄/usr/lib,不需要再寫-L/usr/lib/)

這樣一寫,就OK啦!編譯就成功了!

我們還可以用 nm 工具,來確認libXXX.a到底有木有把pthread_create()函式copy到自己身上。

chenxf@chenxf-PC:~/static_lib_sample$ nm libstatic_lib_example.a

static_lib_example.o:
                 U fwrite
                 U printf
                 U pthread_create
                 U pthread_join
                 U puts
                 U stderr
0000000000000040 T testFunc
0000000000000000 T thread_exe

U表示僅僅呼叫,而沒有定義。也就是該庫並不獨立,而是依賴於其他庫,比如libpthread.so

3 總結

總結一下成果吧!
這裡寫圖片描述
如果有靜態庫libXXX.a,它有個函式叫testFunc(),該函式用了其他的動態庫的函式,比如libAA.so的AA()函式,libBB.so的BB()函式,libCC.so的CC()函式,那麼,該libXXX.a對這些動態庫的呼叫仍是動態呼叫,而不是把動態庫的相關函式copy到自己身上。

任何其他程式,想用libXXX.a,連結時都需要連結libXXX.a所依賴的動態庫。
至於程式跑起來時,動態庫是否要在現場?這個就跟編譯程式加不加-static有關係了。
請看我另一博文就知道。gcc-static命令

anyway,知道真相的你,是不是覺得靜態庫不方便?!
我也覺得!
個人看法是,如果你要寫的靜態庫libXXX.a是完全獨立的,比如裡面只有一些數學運算,不依賴與其他動態庫,那靜態庫挺好的,任何用他的程式,只需要連結時用到,程式跑起來,就不需要它在現場了!

但是,如果你要寫的庫,依賴很多其他的庫,那你還是改寫成動態庫吧!否則,作為寫其他程式的人,如果要用你的庫,那寫Makefile時,還得知道你到底依賴了什麼動態庫,否則編譯都編譯不過,多痛苦啊!!!

4 原始碼

相關推薦

靜態連結動態如何使用靜態

網上有各種靜態庫的建立&使用的例子,但都是超級簡單的例子,比如,靜態庫,就直接來個printf(),就完事了! 其實,實際使用時,靜態庫會複雜很多,比如會呼叫很多其他的動態庫。 下圖就是個例子: 假設libXXX.a用了libpthre

動態靜態編譯測試:含靜態連結動態靜態動態連結靜態動態

本文的目的是測試各種型別庫的編譯後的使用效果,包括庫又連結其他庫的編譯方法,使用方法,依賴性等。 太長不看版:請跳至文章最後的總結對比表。 一。內容包含: ①靜態庫libbb.a依賴靜態庫libaa.a的測試; ②靜態庫libbb.a依賴動態庫libaa.so的測試;

在使用python的selenium 抓取動態網頁瀏覽器內容出現空白的解決方式

轉載請標明出處,謝謝~。 我使用的版本: 1、python 3.7 (IDE 用的 pycharm) 2、selenium(通過pip install 安裝的最新版本:3.14 時間:2018.9.6 ) 3、 geckodriver.exe 21.0 4、fi

iOS 引用外部靜態(.a檔案)Category方法無法載入問題

問題: +[UIImage imageNamedFromBundleWithPNG:]: unrecognized selector sent to class 0x199812698 解決方法為:找到 target 的圖示,更改其 Other Linker Flags

Spring Boot + JPA(hibernate 5) 開發數據表名大小寫問題

hibernate mysql spring boot 大小寫 這幾天在用spring boot開發項目, 在開發的過程中遇到一個問題hibernate在執行sql時,總會提示表不存在。尋找之後發現, 建表時,表統一采用了大寫。hibernate會把大寫統一轉換成小寫。且 mysql在 lin

delphi數據進行增加操作怎麽判斷插入的這個值是否已經存在?

span 數據 for sage dcl 進行 emp rom trim //增 procedure TForm1.btnAddClick(Sender: TObject); begin ADOQuery1.Close; ADOQuery1.SQ

xcode編譯有第三方編譯設定build active architecture only問題

這個屬性設定為yes,是為了debug的時候編譯速度更快,它只編譯當前的architecture版本。 而設定為no時,會編譯所有的版本。 這個是裝置對應的architecture: armv6:iPhone 2G/3G,iPod 1G/2G armv7:iPhone 3GS/4/4s,iPod 3G/4

使用AFNetworking 3.0進行網路請求取消單個佇列和全部佇列的方法(取消網路請求)

        專案中有時會有這種情況,當介面正在請求資料,但資料為返回之前。返回到上一個介面,這種情況下,應取消此介面的網路請求。此篇就是為了處理此種情況下的操作,可        以取消單個請求佇

註冊日本商標利用彩色?還是黑白?

區分 市場 商機 正常 申請人 註冊商標 法國 一個 顏色 註冊日本商標時,該利用彩色?還是黑白? 1、區別首先,在日本商標法上,不區分彩色商標和黑白商標。顏色不一樣的商標基本上認為是同樣的商標。日本商標法第70條中存在註冊商標不考慮色彩的相關規定。 2、類似與否的判斷

【OCP-052】052考試題一變再變完整題收集整理-第15題

manage have table spec bitmap oca alloc true aps 15、Which two are true about space management in tablespaces? A) Locally managed tablespa

當移動到某選單項上選單的背景顏色變為黃色移開變為原來的顏色

<!DOCTYPE html> <html lang="zh"> <head>     <meta charset="UTF-8" />     <meta name="viewport

面試被問到你的優點和缺點如何完美的回答

面試時,面試官經常會問一個問題:“請簡單說一下你的優點和缺點。”對於這個問題,百度上隨便一搜就能找到很多固定的答案,而有的應屆畢業生或職場新人也不稍加修飾,直接把“自己的優缺點”一成不變的背誦出來,給人一種高中背課文的感覺。 面對優缺點的問題,正確的答案一定不是固定的條條框框,而是一種隨機應變的策略,只

java 當本地連線和無線網連結同時存在獲取目標IP同一網段的本地連結IP地址

import java.net.Inet4Address; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java

不再打工!走上創業路的程式設計師 在中小企業面對凜冬期如何活下去?...

點選上方“程式人生”,選擇“置頂公眾號”第一時間關注程式猿(媛)身邊的故事每個人在創業之前,必須

【修真院WEB小課堂】自適應最小螢幕如何佈局。

自適應小螢幕裝置時,該如何佈局?分享人:宜康1.背景介紹隨著科技的發達,使用移動裝置諸如手機平板等獲取資訊,社交的人越來越多。如何在螢幕大小不同的物理裝置上獲得類似的使用體驗呢? 很多網站的做法是為不同大小的物理裝置提供不同的網頁。但是這樣做很麻煩,需要維護多個版本,不夠方便

Android 各大網路請求的比較及實戰android請求實戰

自己學習android也有一段時間了,在實際開發中,頻繁的接觸網路請求,而網路請求的方式很多,最常見的那麼幾個也就那麼幾個。本篇文章對常見的網路請求庫進行一個總結。 HttpUrlConnection 最開始學android的時候用的網路請求是HttpUrlConne

Android Shape Drawable 靜態使用和動態使用(圓角漸變實現)

Android Shape使用場景: 1. 圓角實現 2. 實現有邊框,有填充的背景 3. 實現一個漸變的顏色 一般情況上面三種情況我們會選擇android的shape,下面分別介紹shape的靜態使用和動態使用 1. shape的靜態使用 在drawable中建立一個xml

資料庫表新增的欄位其預設值NULL注意了

資料庫表 新增了一個欄位,其預設值為NULL;例如 InfoType INT(11) DEFAULT NULL 1、當沒有呼叫對應欄位的set方法時,FTL檔案引用該欄位:如 ${Obj.InfoType} 中 引用了該欄位,會出現:undefined 2、實體類中

在Android原始碼中如何吧so打包編譯進入apk 整合第三方(jar和so

整合第三方so和jar包 include $(CLEAR_VARS) #jar包編譯            LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=securitysdk:libs/hello.jar #64和32系統選擇不同的庫 if

(轉載)Android GradientDrawable(shape標籤定義) 靜態使用和動態使用(圓角漸變實現)

最近被吐槽介面太醜,還是很尷尬的,全公司就一個UI設計師,所以很多事情還是不忍直視,一個同事問我,背景可不可以使用漸變的感覺,然後我就有種突然感覺眼前一亮的感覺。還真的沒有做過這方面的東西,單純使用漸變說真的,並不是很讓人感興趣,所以就思考著能不能在自定義視圖裡面直接定義一個