1. 程式人生 > >linux環境下的c++ 動態庫的呼叫

linux環境下的c++ 動態庫的呼叫

主要是為了平時的學習記錄,不妥的地方,煩請指點。

一.下面主要是dlopen開啟動態庫.so相關的API介面函式。

1. void* dlopen(const char* filename,int flag);

filename 是動態庫的path路徑,flag是動態庫載入的幾種方法。

RTLD_LAZY:dlopen返回前,對動態庫中存在的未定義的變數不進行解析,只對函式符號有效,變數符號會被立即載入。

RTLD_NOW: 需要在dlopen返回前,解析出所有未定義符號,如果解析不出來,dlopen時會返回NULL,提示error資訊: undefined symbol: xxxx.......

RTLD_GLOBAL:這個庫中的符號可以被隨後的動態庫使用。


2. char* dlerror(void)

 返回相關的錯誤,如果從初始化到最後結束都沒有錯誤,則返回NULL。

3. void * dlsym(void* handle,const char* symbol);

返回符號為symbol的函式的地址,需要用到dlopen中返回的handle,需要使用dlerror來判斷是否是錯誤,

二.下面舉個簡單的例子說明下。

定義一個基類CTestDL,test()和print() 都是純虛擬函式。C++支援了名稱空間、類以及過載等機制,所以符號的命名規則和C不同。而dl API屬於C的部分,使用的C的命名規則,所以在實現上述兩個函式時(也就是說需要通過動態連結的C++函式)需要使用C的符號命名規則。這需要實現extern 'C'實現。

#ifndef __CTEST_DL_H__
#define __CTEST_DL_H__

class CTestDL
{
	public:
		CTestDL(int a,int b)
		{
			length =a;
			width =b;
		}
	    virtual ~ CTestDL()
		{
		}
	public:
		virtual void test(const char*) =0;
		virtual void print()=0; 
	protected:
		int length;
		int width;
};

extern "C" CTestDL* GetClass(int,int);  //匯出函式名

#endif

下面是一個派生類Test,繼承上面的基類

#include <iostream>

#include "ctest.h"

using namespace std;

class Test :public CTestDL
{
	public:
		Test(int a,int b):CTestDL(a,b) //虛基類已經賦值了
		{
			length = a;
			width = b;
		}
		~Test(){}
	public:
		void test(const char*);
		void print();
	private:
		int length ;
		int width;
};

Test類的cpp檔案:

#include <iostream>
#include <stdio.h>

#include "test.h"
using namespace std;

CTestDL* GetClass(int a,int b)
{
	return new Test(a,b);
}
void Test::test(const char* data)
{
	cout << "--this is a test program !--" <<"**: "<< data << endl;
}

void Test::print()
{
  int area = length * width;
  cout << "**** the area is **** :" << area << endl;
}

編譯的命令: g++ -shared -lc -s -o libtdlc.so test.cpp -fPIC    生成動態庫libtdlc.so

測試程式:

#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include <iostream>
#include "ctest.h"
using namespace std;


typedef CTestDL* (*pTestDLObj)(int,int);  //定義一個函式指標

int main(int argc,char* argv[])
{
	//CTestDL *(*pTestDLObj)(int,int);
	dlerror();
	
	void *lib_dl = dlopen("./libtdlc.so",RTLD_LAZY);
    if(NULL == lib_dl)
    {
        printf("load library libtdlc.so error.\nErrmsg:%s\n",dlerror());
        return -1;
    }
    //pTestDLObj = (CTestDL * (*)(int,int))dlsym(lib_dl,"GetClass");
	pTestDLObj create_class = (pTestDLObj)dlsym(lib_dl,"GetClass");
	
    const char *dlmsg = dlerror();
    if(NULL != dlmsg)
    {
        printf("get class testdl error\nErrmsg:%s\n",dlmsg);
        dlclose(lib_dl);
        return -1;
    }
 
    //CTestDL *pTestdl = pTestDLObj(2,3);
	//CTestDL *pTestdl = (*pTestDLObj)();
	CTestDL* tmp = create_class(3,3);
	tmp->print();
	tmp->test("success full !");
    //pTestdl->print();
    //pTestdl->test("success full ");
 
    delete tmp;
    dlclose(lib_dl);
    return 0;
}

編譯: g++ main.cpp -rdynamic -ldl -s -o dl_main

程式執行的結果:


相關推薦

[轉載總結]Linux環境C++運行時動態鏈接加載要點總結

typedef symbol 類的方法 cout use per 解析 轉換 type 最近在看的一些web服務器源碼的擴展部分基本上都使用到了.so動態庫的運行時加載,也遇到了不少坑,看了不少網上的博客,在這裏稍微總結轉載一下,也是為了以後少走彎路。 首先需要了解的就是靜

windows C++動態的封裝以及呼叫

1、一個程式從原始檔編譯生成可執行檔案的步驟:預編譯 -->  編譯 -->  彙編 --> 連結(1)預編譯,即預處理,主要處理在原始碼檔案中以“#”開始的預編譯指令,如巨集展開、處理條件編譯指令、處理#include指令等。(2)編譯過程就是把預處理完的檔案進行一系列

Linux環境c程序的編譯和執行

環境變量 動態 main.c tor direct 環境 沒有 stdlib.h share 1 單個文件的編譯和執行創建main.c文件,內容如下: #include <stdio.h> #include <stdlib.h> int main

Linux環境c程式的編譯和執行

1 單個檔案的編譯和執行建立main.c檔案,內容如下: #include <stdio.h> #include <stdlib.h> int main(void){ printf("Hello world!\n"); return 0; };   編譯:

windows C++動態的封裝以及調用

文件鏈接 系列 語義分析 ++ 動態鏈接 中大 動態 turn 應用 1、一個程序從源文件編譯生成可執行文件的步驟:預編譯 --> 編譯 --> 匯編 --> 鏈接(1)預編譯,即預處理,主要處理在源代碼文件中以“#”開始的預編譯指令,如宏展開、處理條

linux環境給BOOST編譯靜態加上-fPIC選項

在linux環境下,使用靜態方式編譯boost時,bjam沒有新增-fPIC, 解決辦法如下:  編輯tools/build/v2/tools/gcc.jam檔案,將第391行的 if( $link ) = shared 註釋掉,如下圖:

關於如何在linux環境生成a和so(改,附圖)

一般linux環境下的連結庫分為a庫和so庫,分別表示靜態連結庫和動態連結庫,其作用是把C程式編譯好做成一種可執行連結檔案,c主程式檔案呼叫這些程式的函式介面是可以使用a庫或so庫,在主程式中只需要i

linux 環境 c語言實現mysql資料庫圖片的儲存以及多資料庫直接的轉存

作為一個程式設計師,CSDN對我的程式設計帶來了很多幫助和提高,在這裡可以讓你找到很多開發過程中遇到的問題的解決辦法,今天也寫點自己積累的東西跟大家分享一下,希望對需要的人有幫助. 資料背景:         之前專案一直使用Oracle資料,最近換工作,公司使用的為

gcc,c++ 動態呼叫靜態

生成動態庫: 需要的目標檔案得用-fPIC選項生成. 而靜態庫所需的目標檔案可以不用-fPIC選項. 一個應用程式呼叫動態庫, 而這個動態庫其中的函式呼叫某靜態庫時,如何生成應用程式呢? 例: /////// static.h void static_prin

linux環境 C++效能測試工具 gprof 和gprof2dot

1 簡介 改進應用程式的效能是一項非常耗時耗力的工作,但是究竟程式中是哪些函式消耗掉了大部分執行時間,這通常都不是非常明顯的。GNU 編譯器工具包所提供了一種剖析工具 GNU profiler(gprof)。gprof 可以為 Linux平臺上的程式精確分析效能瓶頸。gprof精確地給出函式被呼叫

Linux 環境C/C++獲取系統時間 && 每隔500ms迴圈一次程式碼實現

環境:NetBeans IDE 8.2 + 遠端主機Linux 獲取當前系統時間getCurrentTime()程式碼如下: #include<sys/time.h> long getCurrentTime(){ struct timeval tv; gett

Linux環境C程式設計指南---gcc 編譯器常用的命令列引數一覽

1. gcc -E source_file.c-E,只執行到預編譯。直接輸出預編譯結果。2. gcc -S source_file.c -S,只執行到原始碼到彙編程式碼的轉換,輸出彙編程式碼。3. gcc -c source_file.c-c,只執行到編譯,輸出目標檔案。4. gcc (-E/S/c/) so

linux環境c++的編寫、除錯以及makefile多檔案連編需要注意的問題

最近剛開始接觸Linux C++,發現其與windows C++有太大的差別。這裡是自己的一些總結,如果有新人看到,希望能夠幫到您。 1、gcc編譯器簡介 生成一個.out需要將原始檔依次進行預處理、

Linux環境軟體()的更新命令

$ sudo apt-get install/delete package$ sudo apt-get -f install                                   #修復安裝$ sudo apt-get dist-upgrade                          

linux環境C語言實現非阻塞方式讀取字串資料的串列埠測試程式,即串列埠工具的編寫

一、前言 1.1 關於串列埠測試工具,網上已經有整合好的應用程式提供大家使用,但其只提供功能介面,內部具體怎麼實現的還需要自己去探索; 1.2 關於串列埠通訊的測試程式在網上已經是數見不鮮,但也不排除很多是直接“參考”別人的(ctrl+c),而且很多程式

linux環境C語言中sleep的問題

printf預設是輸出到標準輸出,而標準輸出預設使用的是行緩衝。在sleep之前fflush(stdout)強制刷緩衝,或者在程式開始使用setbuf(stdout, NULL)禁用緩衝 當然,假如你有足夠的耐心,大約過幾個小時後,緩衝區終於滿了,你會看到效果的。

.net core linux環境 數據連接超時

client 同步 多個數據庫 cor sqlserver sed log 無法定位 表名 最近遇到了一個很奇葩的問題,我編寫了一個.net core程序讀取多個數據庫數據源,進行數據同步處理。該程序在windows環境下運行完全正常,但在linux環境下運行報異常,提示

linux環境c++ 動態呼叫

主要是為了平時的學習記錄,不妥的地方,煩請指點。一.下面主要是dlopen開啟動態庫.so相關的API介面函式。1. void* dlopen(const char* filename,int flag);filename 是動態庫的path路徑,flag是動態庫載入的幾種方

python呼叫C動態匯出函式的返回值為指標型別時,在64位python環境被截斷解決方法

          class my_void_p(c_void_p):               pass                      def sslog_create_instance():               #直接指定 restype=c_void_p在64位上還是會發生地址截

linuxpython呼叫C++動態以及函式

C++:首先C++需要編譯成動態共享庫C++程式碼(cpptest.cpp)如下------#include<iostream>using namespace std;extern "C"{//在extern “C”中的函式才能被外部呼叫int test(){