C 學習(一零八)主程式和動態庫互動

2021-10-07 15:58:54 字數 3973 閱讀 7955

核心關鍵在介面,介面中一定要使用virtual,避免鏈結出現找不到實現的情況。

/

//一般的dll都是特定功能的封裝,主程式只要呼叫其功能即可,比如引數設定dll,

//這些dll不和主程式互動,其只是被動的被呼叫而已。但有時候程式設計要求在dll

//中能呼叫主程式的一些功能,比如主程式有乙個控制器類csysctrl,裡面封裝了對

//外部裝置的訪問,在dll中實現的是使用者介面,希望能在dll中可以呼叫這個控制器類,

//此時如何把這個class傳遞到dll中進行處理呢?以下就是專門用來解決這種問題的。

/要解決這個問題,需要建立乙個主程式專案和至少乙個dll專案。

需要如下簡單幾步即可:

1、建立宣告標頭檔案declare.h,放到目錄inte***ce目錄下

關鍵字afs_framework用來提供給編譯器選擇,在主程式中設定該預編譯項

預編譯項afs_shared_import用於匯出或者匯入後面的介面

//預編譯宣告標頭檔案declare.h

/#include #if defined(afs_framework)

# define afs_shared_import q_decl_export

# define afs_shared_export q_decl_import

#else

# define afs_shared_import q_decl_import

# define afs_shared_export q_decl_export

#endif

/2、建立提供給dll呼叫的主程式功能介面檔案csysctrl.h,也放到inte***ce目錄下

csysctrl是在主程式中實現,提供介面給dll使用,因此用afs_shared_import宣告介面

在主程式中使用時匯出該介面,在dll中使用時匯入該介面

//csysctrl介面宣告標頭檔案csysctrl.h

/#ifndef csysctrl_h

#define csysctrl_h

#include #include "declare.h"

class afs_shared_import csysctrl : public qobject

virtual ~csysctrl(){}

};#endif // csysctrl_h

/3、建立提供給主程式呼叫dll庫的介面檔案canimal.h,也放到inte***ce目錄下

canimal是在dll中實現,提供介面給主程式使用,因此使用afs_shared_export宣告介面

在dll實現該介面並匯出介面宣告,在主程式中僅僅宣告該介面的存在

在dll定義主程式介面指標,並宣告setsysctrl()函式用來引入該介面指標,

這個函式必須宣告為virtual型別的純虛函式,否則可能鏈結不成功,因為編譯器找不到實現**

//canimal介面宣告標頭檔案canimal.h

/#ifndef canimal_h

#define canimal_h

#include #include "declare.h"

#include "csysctrl.h"

//介面宣告

class afs_shared_export canimal : public qobject

virtual ~canimal(){}

protected:

csysctrl* m_sysctrl;

};#endif // canimal_h

/4、建立c++共享庫dll專案

4.1、在配置檔案中加入includepath += ../inte***ce一行,在編譯環境中包含該目錄

4.2、然後將canimal.**件新增到該專案中

4.3、刪除專案中*_global.**件,因為這個宣告已經被包含在declare.**件中了

4.4、修改專案中存在的類,使其繼承自canimal類,並實現其中的純虛函式介面

4.5、建立匯出介面函式createdog()和releasedog(),用來建立和釋放派生物件

示例:這裡派生類採用了單例模式,方便後續使用

//派生類dogtest的標頭檔案dogtest.h

/#ifndef dogtest_h

#define dogtest_h

#include "canimal.h"

#define afs dogtest::instance()->getsysctrl()

//建立dogtest物件

extern "c" q_decl_export canimal* createdog();

extern "c" q_decl_export void releasedog();

class dogtest : public canimal

protected:

dogtest();

private:

static dogtest* s_instance;

};#endif // dogtest_h

///派生類dogtest的實現檔案dogtest.cpp

/#include "dogtest.h"

#include "canimal.h"

#include canimal* createdog()

void releasedog()

dogtest::dogtest()

: canimal()

dogtest* dogtest::s_instance = null;

dogtest* dogtest::instance()

void dogtest::setsysctrl(csysctrl *sysctrl)

bool dogtest::eat()

void dogtest::sleep()

/5、建立主程式專案

5.1、在配置檔案中加入includepath += ../inte***ce一行,在編譯環境中包含該目錄

5.2、在配置檔案中加入defines += afs_framework一行,宣告該專案為主程式

5.3、然後將csysctrl.**件新增到該專案中

5.4、新增乙個cmyctrl類,派生自csysctrl介面,並實現其中的純虛函式

//派生類cmyctrl的標頭檔案cmyctrl.h

/#ifndef cmyctrl_h

#define cmyctrl_h

#include #include "csysctrl.h"

class cmyctrl : public csysctrl

;#endif // cmyctrl_h

///派生類cmyctrl的實現檔案cmyctrl.cpp

/#include "cmyctrl.h"

#include csysctrl::csysctrl(qobject *parent)

: qobject(parent)

csysctrl::~csysctrl()

cmyctrl::cmyctrl(qobject *parent) :

csysctrl(parent)

void cmyctrl::walkwithdog()

void cmyctrl::playwithdog()

/4、載入動態庫,匯出dll中的類

//動態載入dll

/#include "widget.h"

#include "canimal.h"

#include "ui_widget.h"

widget::widget(qwidget *parent) :

qwidget(parent), m_dog(null),

ui(new ui::widget)}}

}widget::~widget()

void widget::on_pushbutton_clicked()

/

二、主程式和動態庫不在乙個資料夾中

動態庫與主程式共享全域性變數

曾經在一次寫程式的時候,全域性使用乙個日誌物件,所有的日誌資訊都由此日誌物件寫入檔案。但是發現在動態鏈結庫裡,無法訪問到該全域性物件,後經查詢資料。發現,動態鏈結庫是否能訪問主程式的全域性變數,主程式是否能訪問動態鏈結庫裡定義的全域性變數都是可以通過鏈結指令改變此行為。主程式訪問動態鏈結庫裡的全域性...

c 呼叫靜態庫和動態庫

呼叫靜態庫 第一步把動態庫放到檔案裡 第二部連線上靜態庫 pragma comment lib,靜態庫.lib 呼叫動態庫 第一步 typedef int getmaxnum int,int 定義乙個函式指標型別 第二部 載入 dll hmodule hmodule loadlibrary mydl...

c和c 互相呼叫動態庫

平時需要接觸c和c 有時會遇到兩種語言互相呼叫動態庫的情況,這時就要對 進行一些處理,做個記錄。兩種語言生成的庫是無法直接互相呼叫的,原因在於c 支援過載,因此存在改名機制 也可能是因為有改名機制所以支援過載 即生成的中間檔案會對函式名進行改寫,會將函式名與引數列表相結合生產新的函式名,這樣就可以通...