dlopen呼叫動態庫單例項類,巨集定義重名問題測試

2021-09-27 09:14:19 字數 2974 閱讀 1062

main.cpp

#include #include #include #include #include #include #include using namespace std;

typedef void(*check_func)();

void test_printa()

void test_call(string path_str)

cout << "開啟動態庫" << path_str << "成功" << endl;

dlerror();

//獲取乙個函式databasemodelcheck

if ((error = dlerror()) != null)

char *pbuff = null;

int buff_len = 0;

string err_info = "";

(*cac_func)();

if (pbuff != null)

cout << endl << endl;

//關閉動態鏈結庫

dlclose(handle);

return ; }}

int main()

print.cpp

#ifndef _print_h_

#define _print_h_

#include #include "print.h"

#include using namespace std;

#define plog print::getinstance()

class print

cout<

};extern "c" void test_print();

#endif

print.cpp

#include #include "print.h"

#include using namespace std;

using test_lib::print;

print* print::m_instance = null;

void test_print()

printa.h

#ifndef _printa_h_

#define _printa_h_

#include #include #include "printa.h"

using namespace std;

extern "c" void test_print();

#define plog print::getinstance()

class print

cout<

mapb;

float c;

};#endif

printa.h

#include #include #include "printa.h"

using namespace std;

print* print::m_instance = null;

void test_print()

編譯命令:

g++ main.cpp -o main -ldl -la -i. -l. -wl,-rpath=.

g++ -g -shared -fpic -fpermissive print.cpp -o libb.so

g++ -g -shared -fpic -fpermissive printa.cpp -o liba.so

輸出結果為:

可以看到程式只初始化了liba.so中的print物件,並且dlopen呼叫libb.so時test_print()使用的也是liba.so中的函式位址。

所以程式在初始化時只會載入乙份print物件。但是我們可以換種寫法,

將print.h中的void printa()修改為void printa(int);

重新編譯libb.so之後,執行main

可以看到plog的指標還是同乙個,但是執行printa函式的指標已經指向print.h裡的函式。第乙個成員a的位址沒變,目前沒有對記憶體進行操作,這時候記憶體已經有點混亂了,如果對記憶體進行讀寫,很可能造成堆疊錯誤,core。如果將printa()注釋掉的map.find放開,我這裡測試會卡死。另乙個專案測試會崩潰。

這個情況有點類似於函式的過載,又有點像基類呼叫子類的新增函式,都是指標指向了不在作用域範圍的位址。

問題到這已經定位出來了,具體原因還是在動態庫載入,函式指標,類指標是如何載入的。

解決方法:

可以申請乙個命名空間,將print.h中的類包括進去。這樣在呼叫的時候會重新建乙個該命名空間下的單例項,不影響使用。

後續又做了另外乙個測試;

main不引用printa.h,通過dlopen進行呼叫a,b。

編譯時不引用a,b兩個動態庫。

g++ main.cpp -o main -ldl

執行結果:

這裡顯示對每乙個單例項都初始化了一次,這裡懷疑是因為每次呼叫都會dlclose的緣故。

如果這樣編譯:

g++ main.cpp -o main -ldl -la -i. -l. -wl,-rpath=.

執行結果如下:

感覺和動態庫載入的順序有些關係。具體為什麼不太清楚,但是已經解決問題就不繼續了

dlopen動態載入動態庫

為了使程式方便擴充套件,具備通用性,可以採用外掛程式形式。採用非同步事件驅動模型,保證主程式邏輯不變,將各個業務已動態鏈結庫的形式載入進來,這就是所謂的外掛程式。linux提供了載入和處理動態鏈結庫的系統呼叫,非常方便。本文先從使用上進行總結,涉及到基本的操作方法,關於動態鏈結庫的本質及如何載入進來...

dlopen動態庫訪問

因專案需要多程序共享資源訪問.include include include typedef struct titem typedef structtbank typedef struct tbankctrl static titem g titem static tbank g tbank sta...

dlopen 和 dlsym 動態呼叫函式

dlopen 開啟乙個庫,獲取控制代碼。開啟so檔案獲取控制代碼 看作基位址 dlsym 在開啟的庫中查詢符號的值。so裡面查某個函式位址 dlclose 關閉控制代碼。dlerror 返回乙個描述最後一次呼叫dlopen dlsym,或 dlclose 的錯誤資訊的字串。import typede...