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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

DLL导出函数名称改编的解决方法

發布時間:2023/12/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DLL导出函数名称改编的解决方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

***************************************************

更多精彩,歡迎進入:http://shop115376623.taobao.com

***************************************************


1.DLL編譯后導出函數名稱改變

?

在編寫一個DLL后,為了能被別的程序調用,需要將被使用的函數導出;

但是一般的編譯器都會將到處函數名稱改變;

例如:在VC中新建一個空的win32 dll工程,然后添加下面的文件;

[cpp]?view plaincopy
  • //dll1.h??
  • #ifdef?DLL_API?_declspec(dllexport)???
  • #else??
  • #define?DLL_API?_declspec(dllexport)??
  • #endif??
  • ??
  • DLL_API?int?add(int?a,?int?b);??
  • [cpp]?view plaincopy
  • //dll1.cpp??
  • ??
  • #include?"dll1.h"??
  • ??
  • DLL_API?int?add(int?a,?int?b)??
  • {??
  • ??return?a?+?b;??
  • }??
  • ?

    編譯以后,得到dll1.dll與dll1.lib;使用Dumpbin.exe或者是Depends工具查(dll查看器)看發現,

    dll1.dll中的到處函數名稱為:?add@@YAHH@Z?;這個新的函數名稱是C++編譯器對add函數的名稱進行了改變,

    而且不同的編譯器的改編規則也不一樣,這就導致在通過add函數名對函數進行調用時無法找到add函數

    因為此時add的函數名稱已經被改編;

    ?

    2.限定導出函數名稱

    ?

    為了解決C與C++能在不同編譯器之間正常調用DLL,所以我們希望DLL在編譯過程中不要對函數名稱進行改編;

    我們可以在定義導出函數時,加上限定符 extern "C"

    我們把上面的例子修改下:

    [cpp]?view plaincopy
  • //dll1.h??
  • #ifdef?DLL_API?extern?"C"?_declspec(dllexport)???
  • #else??
  • #define?DLL_API?extern?"C"?_declspec(dllexport)??
  • #endif??
  • ??
  • DLL_API?int?add(int?a,?int?b);??
  • ?

    [cpp]?view plaincopy
  • //dll1.cpp??
  • #include?"dll1.h"??
  • ??
  • DLL_API?int?add(int?a,?int?b)??
  • {??
  • ??return?a?+?b;??
  • }??
  • 我們再次編譯得到dll1.dll,通過工具查看其到導出函數發現,此時的add函數的導出名稱仍然是add;

    這樣我們就可以在其他編譯器上直接通過add調用該函數了;

    ?

    3.__stdcall關鍵字將使限定無效

    如果我們在第二個的基礎上給函數加上__stdcall關鍵字,導出函數的名稱將仍然被改編;

    如果沒有添加__stdcall關鍵字,那么函數調用約定為C調用約定。如果加了__stdcall標準調用約定,

    就是WINAPI調用約定,也就是pascal調用約定,這種約定與C調用約定不一樣。

    [cpp]?view plaincopy
  • //dll1.h??
  • #ifdef?DLL_API?extern?"C"?_declspec(dllexport)???
  • #else??
  • #define?DLL_API?extern?"C"?_declspec(dllexport)??
  • #endif??
  • ??
  • DLL_API?int?__stdcall?add(int?a,?int?b);??
  • ?

    [cpp]?view plaincopy
  • //dll1.cpp??
  • #include?"dll1.h"??
  • ??
  • DLL_API?__stdcall?int?add(int?a,?int?b)??
  • {??
  • ??return?a?+?b;??
  • }??
  • 重新編譯,然后通過工具查看DLL的導出函數,發現名稱為: _add@8;

    也就是說如果函數的調用約定發生變化,即使在聲明時使用了 extern "C"限定符,函數名稱仍然會

    改編;

    C語言與Delphi的調用約定是不一樣的,Delphi使用的是pascal調用約定,如果我們要用C寫一個DLL供Delphi使用,

    那么在導出函數時應指定其使用標準的函數調用約定,但此時 導出函數名稱就會被改編;

    ?

    在這種情況下,我們需要通過一個稱為模塊定義文件(DEF)的方法解決名稱被改編的問題;

    ?

    在上面例子的基礎上,我們給這個工程添加一個后綴為def的文件dll1.def;然后添加如下代碼:

    [c-sharp]?view plaincopy
  • //dll1.def??
  • ??
  • LIBRARY?"dll1"??
  • ??
  • EXPORTS??
  • add??
  • 此文件中LIBRARY指定動態鏈接庫的內部名稱,該名稱與生成的動態鏈接庫名稱要匹配;

    EXPORTS下面就是要導出的函數

    如果EXPORTS下的函數個數多時,方式為:

    LIBRARY “dlll”

    EXPORTS

    ADD

    SUB

    MUL

    ……

    如果導出的函數名稱與源文件中的函數名稱不一樣可以通過下面的語法指定導出函數名稱:

    entryname = internalname

    ?

    編譯時,編譯器會按照def中指定的函數名稱導出函數;

    ?

    重新編譯,通過工具查看dll1.dll中的導出函數為add了;

    總結

    以上是生活随笔為你收集整理的DLL导出函数名称改编的解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。

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