C linux動態庫so匯出及使用

2021-09-16 13:19:22 字數 4110 閱讀 4910

存在不相容的函式

控制linux動態庫的匯出函式

使用linux動態庫

靜態載入

其他問題

第一次嘗試匯出linux動態庫,包裝log4cpp,遇到的問題做個記錄。

在官網上下下來包過後,官網的安裝說明不全:

// stdcall & cdecl

#if defined(_msc_ver) || defined(_win32) || defined(_win64)

#define tce_api __stdcall

// tcelogger_dll_exports

#ifdef tcelogger_dll_exports

#define dll_api __declspec(dllexport)

#else

#define dll_api __declspec(dllimport)

#endif

#else

#define tce_api

#define dll_api

#endif

主要是linux:

args… 對應 ##args // qt會提示這種表示是gnu擴充套件

windows:

… 對應 ##__va_args__

// linux下:

#define info(logformat, args...) info(__function__, __line__, logformat, ##args)

// windows下:

#define info(logformat, ...) info(__function__, __line__, logformat, ##__va_args__)

參考:

發現有的函式是windows平台的。sprint_s是windows平台下執行緒安全的格式化字串函式並非標準c函式,因此linux下無法使用,但可以使用snprintf函式代替。

int

snprintf

(char

*dest, size_t n,

const

char

*fmt,..

.);// 函式原型相同,替換即可

#define sprintf_s snprintf

windows下通過__declspec(dllexport)來宣告dll動態庫匯出的介面(函式或類),__declspec(dllimport)來宣告為動態庫載入的介面。linux下不可用。

linux下,gcc幫助文件 -fvisibility=default|internal|hidden|protected 引數下有這麼一段話:

總結是:

linux下原始檔中的所有函式都有乙個預設的visibility屬性,預設為public,即預設匯出。如果要隱藏,則在gcc編譯指令中加入-fvisibility=hidden引數,會將預設的public屬性變為hidden。

隱藏函式匯出後,所有的匯出都隱藏,再在原始碼中,在需要匯出的函式前新增 __attribute__ ((visibility(「default」))) ,使其仍按預設的public屬性處理。

檢視檔案屬性:

檢視匯出函式:

linux提供4個庫函式、乙個標頭檔案dlfcn.h以及兩個共享庫(靜態庫libdl.a和動態庫libdl.so)支援動態鏈結。

dlsym:返回鎖請求的入口點的指標

dlerror:返回null或者指向描述最近錯誤的字串

dlclose:關閉動態共享檔案

使用linux的庫,使用方法和windows下一致。

#include

#include

#include

"tcelogger.h"

using

namespace std;

using

namespace tce;

// declare function pointer

typedef tcelogger&

(*type_pso_tlgi)

(void);

intmain()

// use dlsym to get function address (in windows getprocaddress)

type_pso_tlgi pso_tlgi =

(type_pso_tlgi)

dlsym

(pso_handle,

"tceloggergetinstance");

if(!pso_tlgi)

// use function to get instance

tcelogger& logger =

pso_tlgi()

; logger.

info

("ok");

return0;

}

動態載入cmakelist

動態載入時,需要使用dl庫,在cmakelist中新增鏈結dl庫。

cmake_minimum_required

(version 2.8

)project

(socaller)

// 設定debug模式

set(cmake_build_type debug)

//設定c++11

set(cmake_cxx_flags "$ -std=c++11"

)// qt工程中顯示**件

file

(glob_recurse libfiles "tcelogger.h"

)add_custom_target

(headers sources $

)// 設定include目錄

include_directories($)

// 設定庫目錄

link_directories($)

// 設定生成內容

add_executable

($"socaller.cpp"

)// 設定要鏈結的庫

target_link_libraries

($ dl

tcelogger //當靜態載入時直接鏈結

)

參考:

在cmakelist中設定鏈結該動態庫後,幷包含標頭檔案,可以直接使用。

// 使用動態庫匯出的c介面函式獲取例項

tcelogger& tcelogger =

tceloggergetinstance()

;tcelogger.

crit

("ok");

return

0;

在cmakelist中新增set(cmake_build_type debug)

在用測試demo debug時發現,dlopen失敗報錯是沒有找到log4cpp.so,原來是生成so時,鏈結的log4cpp庫沒有字尾:

target_link_libraries

($ log4cpp)

這樣會預設鏈結動態庫log4cpp.so,修改為

target_link_libraries

($ log4cpp.a)

修改鏈結log4cpp.a靜態庫後,報錯relocation r_x86_64_32 against `.rodata』 can not be used when ****** a shared object。

原因是如果將編譯的靜態庫鏈結進動態庫使用,也就是我的應用情景,需要在編譯靜態庫時,加上編譯指令 -fpic 。

因此在log4cpp原始碼的cmakelist中,增加指令:

set

(cmake_cxx_flags "$ -fpic"

)

然後不使用configure,直接cmake make,生成靜態庫,解決。

參考:cmakelist 編寫規則:

target_link_libraries

($ pthread)

解決問題。

so動態庫的成及測試

so檔案是是elf格式檔案,共享庫 動態庫 類似於dll。節約資源,加快速度,公升級簡化。例子中測試檔案的生成 gcc g ts.c o ts l.ls 一下是例子 先寫乙個c檔案 s.c 1.include 2.int count 3.void out msg const char m 4.6.測...

靜態庫 a和動態庫 so生成及呼叫

gcc編譯器工具一般位於 usr bin或者 usr local bin目錄,但它會從其它位置執行各種編譯器支援的應用程式,這個位置可能是 usr lib gcc lib 目錄,gnu c c 編譯器的各個工具和gnu專用標頭檔案都儲存在這裡。標頭檔案,一般位於 usr include,包含標頭檔案...

so檔案動態替換方法及Linux動態庫的用法

在替換so檔案時,如果在不停程式的情況下,直接用 cp new.so old.so 的方式替換程式使用的動態庫檔案會導致正在執行中的程式崩潰。解決的辦法是採用 rm cp 或 mv cp 來替代直接 cp 的操作方法。linux系統的動態庫有兩種使用方法 執行時動態鏈結庫,動態載入庫並在程式控制之下...