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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

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

更多精彩,歡迎進(jìn)入:http://shop115376623.taobao.com

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


1.DLL編譯后導(dǎo)出函數(shù)名稱改變

?

在編寫一個(gè)DLL后,為了能被別的程序調(diào)用,需要將被使用的函數(shù)導(dǎo)出;

但是一般的編譯器都會(huì)將到處函數(shù)名稱改變;

例如:在VC中新建一個(gè)空的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查看器)看發(fā)現(xiàn),

    dll1.dll中的到處函數(shù)名稱為:?add@@YAHH@Z?;這個(gè)新的函數(shù)名稱是C++編譯器對(duì)add函數(shù)的名稱進(jìn)行了改變,

    而且不同的編譯器的改編規(guī)則也不一樣,這就導(dǎo)致在通過add函數(shù)名對(duì)函數(shù)進(jìn)行調(diào)用時(shí)無法找到add函數(shù)

    因?yàn)榇藭r(shí)add的函數(shù)名稱已經(jīng)被改編;

    ?

    2.限定導(dǎo)出函數(shù)名稱

    ?

    為了解決C與C++能在不同編譯器之間正常調(diào)用DLL,所以我們希望DLL在編譯過程中不要對(duì)函數(shù)名稱進(jìn)行改編;

    我們可以在定義導(dǎo)出函數(shù)時(shí),加上限定符 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;??
  • }??
  • 我們?cè)俅尉幾g得到dll1.dll,通過工具查看其到導(dǎo)出函數(shù)發(fā)現(xiàn),此時(shí)的add函數(shù)的導(dǎo)出名稱仍然是add;

    這樣我們就可以在其他編譯器上直接通過add調(diào)用該函數(shù)了;

    ?

    3.__stdcall關(guān)鍵字將使限定無效

    如果我們?cè)诘诙€(gè)的基礎(chǔ)上給函數(shù)加上__stdcall關(guān)鍵字,導(dǎo)出函數(shù)的名稱將仍然被改編;

    如果沒有添加__stdcall關(guān)鍵字,那么函數(shù)調(diào)用約定為C調(diào)用約定。如果加了__stdcall標(biāo)準(zhǔn)調(diào)用約定,

    就是WINAPI調(diào)用約定,也就是pascal調(diào)用約定,這種約定與C調(diào)用約定不一樣。

    [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的導(dǎo)出函數(shù),發(fā)現(xiàn)名稱為: _add@8;

    也就是說如果函數(shù)的調(diào)用約定發(fā)生變化,即使在聲明時(shí)使用了 extern "C"限定符,函數(shù)名稱仍然會(huì)

    改編;

    C語言與Delphi的調(diào)用約定是不一樣的,Delphi使用的是pascal調(diào)用約定,如果我們要用C寫一個(gè)DLL供Delphi使用,

    那么在導(dǎo)出函數(shù)時(shí)應(yīng)指定其使用標(biāo)準(zhǔn)的函數(shù)調(diào)用約定,但此時(shí) 導(dǎo)出函數(shù)名稱就會(huì)被改編;

    ?

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

    ?

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

    [c-sharp]?view plaincopy
  • //dll1.def??
  • ??
  • LIBRARY?"dll1"??
  • ??
  • EXPORTS??
  • add??
  • 此文件中LIBRARY指定動(dòng)態(tài)鏈接庫(kù)的內(nèi)部名稱,該名稱與生成的動(dòng)態(tài)鏈接庫(kù)名稱要匹配;

    EXPORTS下面就是要導(dǎo)出的函數(shù)

    如果EXPORTS下的函數(shù)個(gè)數(shù)多時(shí),方式為:

    LIBRARY “dlll”

    EXPORTS

    ADD

    SUB

    MUL

    ……

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

    entryname = internalname

    ?

    編譯時(shí),編譯器會(huì)按照def中指定的函數(shù)名稱導(dǎo)出函數(shù);

    ?

    重新編譯,通過工具查看dll1.dll中的導(dǎo)出函數(shù)為add了;

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。