使用def文件簡化dll導出


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

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

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

    

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

    extern "C" _declspec(dllexport) int add(int a, int b);

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

    

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

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

    

Def文件的簡單示例如下:

    LIBRARY
    EXPORTS
        add

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

    

這樣,我們的函數無需加那一堆前綴,仍然可以使用默認的int add(int a, int b);形式,但導出后的方式然是C形式的函數定義。

    

最后指得一提的是,一般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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM