日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】extern “C“以及__declspec(dllexport) 讲解和def文件dll导出方法

發布時間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】extern “C“以及__declspec(dllexport) 讲解和def文件dll导出方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:https://blog.csdn.net/qing666888/article/details/41135245

一,__ declspec(dllexport):
將一個函數聲名為導出函數,就是說這個函數要被其他程序調用,即作為DLL的一個對外函數接口。通常它和extern“C”合用,形式如下:

extern "C" {__declspec(dllexport) void FUNCTION(){ } }


這是由于在制作DLL導出函數時由于C ++存在函數重載,因此__declspec(dllexport)FUNCTION(int,int)在DLL會被裝飾,例如被裝飾成為function_int_int,而且不同的編譯器decorate的方法不同,造成了在用GetProcAddress的的取得FUNCTION地址時的不便,使用外部的“C”時,上述的裝飾不會發生,因為?沒有函數重載,如此一來被外部的“C”修飾的函數,就不具備重載能力。

二,MSDN:
“在32位編譯器版本中,可以使用__declspec(dllexport)關鍵字從DLL導出數據,函數,類或類成員函數.__ declspec(dllexport)將導出指令添加到對象文件(即obj文件) ,若要導出函數,__ declspec(dllexport)關鍵字必須出現在調用約定關鍵字的左邊(如果指定了關鍵字)。例如:__ declspec
(dllexport)void __cdecl Function1(void);

若要導出類中的所有公共數據成員和成員函數,關鍵字必須出現在類名的左邊,如下所示:
class __declspec(dllexport)CExampleExport:public CObject
{... class definition ...};

生成DLL時,通常創建一個包含正在導出的函數原型和/或類的頭文件,并將__declspec(dllexport)的添加到頭文件中的聲明。
若要提高代碼的可讀性,請為__declspec(DLLEXPORT )定義一個宏并對正在導出的每個符號使用該宏:
#define DllExport __declspec(dllexport)“

三,__ declspec(dllexport)與.def
模塊定義(.def)文件是包含一個或多個描述各種DLL屬性的模塊語句的文本文件
.1,二者的目的都是將公共符號導入到應用程序中或從DLL導出函數
.2,添加__declspec(dllexport)是為了提供不使用.def文件從.EXE或.DLL導出函數的簡單方法
.3,如果不使用__declspec(dllimport)或__declspec(dllexport)導出DLL函數,則DLL需要.def文件
.4,并不是任何時候選擇添加__declspec(dllexport)而放棄.def的方式都是好的。如果DLL是提供給VC ++用戶使用的,只需要把編譯DLL時產生的。 lib提供給用戶,它可以很輕松地調用你的DLL。但是如果DLL是供VB,PB,Delphi用戶使用的,那么會產生一個小麻煩。因為VC ++對于__declspec(dllexport)聲明的函數會進行名稱轉換,如下面的函數:__ declspec?
? ? ?(dllexport)int __stdcall IsWinNT()?
? ? ?會轉換為IsWinNT @ 0,這樣你在VB中必須這樣聲明:?
? ? ?聲明函數IsWinNT Lib“my.dll”別名“IsWinNT @ 0”()As Long?
? ? ?@的后面的數由于參數類型不同而可能不同。這顯然不太方便。所以如果要想避免這種轉換,就要使用.DEF文件方式。

?

?

在C ++中,我們可以通過??__declspec(DLLEXPORT)??將函數導出為DLL的中供其它程序使用,例如:

????_declspec?dllexport?int?add(int?a,int?b);

在這種方式下,如果調用該DLL的是一個C ++程序(同一個編譯器的版本)是沒有問題的。但是,如果調用該DLL是一個其它語言的程序(如C#,VB),則會出錯。究其原因,是因為在C ++中存在函數的重載,允許函數重名,因此在編譯器生成的DLL的時候,為了區別重名的程序,其會將進行一定算法進行名稱轉換。例如,對于前面的添加函數,實際的函數名稱是如下形式。

????

因此,我們直接通過函數名add是無法找到該函數的,從而導致調用失敗。為了解決這一問題,我們往往在函數前面再加一個extern?“C”,?使用C方式的函數命名規則。

????extern?“C”?_declspec?dllexport?int?add(int?a,int?b);

這樣函數的名稱就成加了。

????

這樣,我們就需要在每一個函數簽名加上“?extern?”C“?_declspec?dllexport??”?這一長串聲明。如果需要導出的函數較多則顯得非常繁瑣,也非常難看。為了簡化這一過程, MS引入了高清文件網求方便我們操作。

使用默認值文件比較簡單,只需要在項目中添加一個DEF文件,然后把我們要導出的函數放在DEF文件中即可。

????

DEF文件的簡單示例如下:

????LIBRARY
????EXPORTS
????????添加

最后記得在鏈接器選項中選中使用的DEF文件(默認情況下,添加DEF文件時會自動加上該選項,無需手動更改)。

????

這樣,我們的函數無需加那一堆前綴,仍然可以使用默認的INT?添加(詮釋一個,INT?B);形式,導出但后的方式然的英文?形式的函數定義。

????

最后指得一提的是,一般的C / C ++默認的調用方式是__cdecl,這種方式下需要調用方對函數清棧。如果對外提供API共其它非C ++程序使用時,調用方會無法清棧而出錯(C#會直接報函數聲明不匹配的錯誤)。因此,對外提供api時還應該將接口聲明為__stdcall,讓api函數自己清棧。這也是Windows API前面都加上了一個WINAPI的宏的原因。

def文件還有許多其它的高級用法,要進一步了解的話,可以參看一下MS的官方文檔:http://msdn.microsoft.com/zh-cn/library/28d6s79h(?v = vs.80).aspx

?

總結

以上是生活随笔為你收集整理的【转】extern “C“以及__declspec(dllexport) 讲解和def文件dll导出方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。