第19章動態鏈結庫鏈結外部的客戶端(三)

2021-12-30 01:20:00 字數 3604 閱讀 7567

動態鏈結庫鏈結外部的客戶端

在工程名"dll"標頭檔案,新增:

#ifdef dll_api

#else

#define dll_api _declspec(dllimport)

dll_api int add(int a,int b);

dll_api int jianfa(int a,int b);在工程名"dll"原始檔,新增:

#define dll_api _declspec(dllimport)

#include"dll.h"

int add(int a,int b)

int jianfa(int a,int b)

編譯後,把dll.dll和dll.lib複製貼上給工程名為「dlltest」目錄當中。

訪問動態鏈結庫的類:

在工程名"dll"標頭檔案,新增:

#ifdef dll_api

#else

#define dll_api _declspec(dllimport)

dll_api int add(int a,int b);

dll_api int jianfa(int a,int b);

class dll_api point

;在工程名"dll"原始檔,新增:

#define dll_api _declspec(dllimport)

#include"dll.h"

#include

#include

int add(int a,int b)

int jianfa(int a,int b)

void point::output(int x,int y)

getforegroundwindow函式,可以當前使用的控制代碼

將編譯生成的dll和lib檔案複製貼上到dlltest檔案目錄。

在"dlltest"新增按鈕,其函式內容為:

void cdlltestdlg::onoutput()

編譯執行,視窗顯示:

x5,y=3

意味著匯出dll的類,還匯出了成員函式output。

如果不想匯出dll整個類,只是匯出指定的成員函式。

在「dll」標頭檔案當中,修改為:

#ifdef dll_api

#else

#define dll_api _declspec(dllimport)

dll_api int add(int a,int b);

dll_api int jianfa(int a,int b);

class /*dll_api*/ point

;在「dll」原始檔當中,實現:

#define dll_api _declspec(dllimport)

#include"dll.h"

#include

#include

int add(int a,int b)

int jianfa(int a,int b)

void point::output(int x,int y)

////////////////////////////////////////

void point::test()

/////////////////////////////////////用dumpbin檢視一下,查出dll沒有匯出test,而匯出了指定的成員函式output.

然後把」dll「工程的目錄裡面的dll和.lib複製貼上給工程名為「dlltest」目錄當中。

在「dlltest」工程,編譯一下,執行,結果和匯出整個類一樣。

ps:雖然dll中沒有匯出類,但是在外部還可以宣告其類的物件,利用物件去呼叫被匯出的成員函式。

如果成員函式是私有的,即使被匯出了,還因為訪問許可權而不能被呼叫。

額外知識筆記:

1.如果用c++編譯的動態鏈結庫,匯出的成員函式名字會發生變化。當用c語言編寫的客戶端去訪問這個動態鏈結庫

就不能識別出被匯出的成員函式,因為名字識別不出來。

2.如果用c++編寫的客戶端就可以訪問c++編寫的被匯出的函式,因為改變名字是同一種語言的編譯器可以識別出來。

3.如果換成其他的c++編寫的客戶端也不能訪問被匯出的函式。

為了解決這個問題,解決辦法是不要讓函式名稱發生改變:

在「dll」標頭檔案當中,修改為:

#ifdef dll_api

#else

#define dll_api extern "c"/*此處修改,一定要大寫字母*/ _declspec(dllimport)

dll_api int add(int a,int b);

dll_api int jianfa(int a,int b);

class /*dll_api*/ point

;在「dll」原始檔當中,實現:

#define dll_api extern "c"/*此處修改,一定要大寫字母*/ _declspec(dllimport)

#include"dll.h"

#include

#include

int add(int a,int b)

int jianfa(int a,int b)

void point::output(int x,int y)

編譯後,在執行dumpbin可以檢視函式名字。

extern "c"的缺陷:

不能夠匯出類的成員函式,只能匯出全域性函式,如:

dll_api int add(int a,int b);

dll_api int jianfa(int a,int b);

而不能匯出類的成員函式:

class /*dll_api*/ point

;如果呼叫約定改變,即使有extern"c",也怒能匯出函式。

為了解決這個問題,在「dll」標頭檔案當中,修改為:

dll_api int _stdcall add(int a,int b);

dll_api int _stdcall jianfa(int a,int b);

使用標準呼叫約定_stdcall。

在「dll」原始檔當中,修改:

int _stdcall add(int a,int b)

int _stdcall jianfa(int a,int b)

編譯後,檢視函式名字沒有變化,顯示為:

_add@8

_jianfa@8

8表示被匯出函式所佔的位元組數

為解決名字改編問題(利用新增def檔案),下篇文章再做筆記。

第21章 動態鏈結庫

一 動態鏈結庫基本知識 1 動態鏈結庫模組可以有任何副檔名 exe,fon 但其標準副檔名是,dll。只有擴充套件名為.dll的動態鏈結庫才能被windows作業系統自動載入,否則明確的用loadlibrary,loadlibraryex 三 lib庫 擴充套件名為lib的檔案分物件庫和導入庫 1 ...

第19講 動態鏈結庫

declspec dllexport 識別符號宣告的函式效率更高,相對於用extern 3,可以用dependency walker檢視動態鏈結庫中匯出的函式 4,如果動態鏈結庫專案中源程式自己要使用動態鏈結庫函式,則在動態鏈結庫標頭檔案中使用預編譯巨集 ifdef dll1 api else de...

Chap 19 動態鏈結庫

chap 19 動態鏈結庫 一 只有在其他模組呼叫動態鏈結庫中的函式時,它才發揮作用。win32 api 中所有的函式都在dll 中,其中最重要的三個dll 1.kernel32.dll 所有與記憶體操作,執行緒,程序相關的操作。2.user32.dll 所有與執行使用者介面相關的操作。3.gdi3...