總結一下DLL宣告的一些問題

2021-05-11 15:09:34 字數 2714 閱讀 5846

有關dll的問題現在資料很多,但是很多人寫dll時經常出現呼叫程式無法找到相關的匯出函式的問題,這裡主要的原因是dll在宣告時出的問題。

在這裡主要有兩個問題,乙個是呼叫約定的問題,乙個是函式名修飾的問題,而這兩個問題又是相互影響的。

一:宣告為:extern "c" int __declspec(dllexport)add(int x, int y);

這種宣告是強制用c語言方式進行修飾,且用c的預設約定,即__cdecl方式。這種方式編譯產生的dll中有乙個匯出函式:add,不加任何修飾。

二:宣告為:extern "c" int __declspec(dllexport) __stdcall add(int x, int y);

這種宣告是強制用c語言方式進行修飾,且用stdcall約定,這種方式編譯產生的dll中有乙個匯出函式:_add@8,即前面有「_」,後面加了引數長。

三:宣告為:int __declspec(dllexport) __stdcall add(int x, int y);

這種宣告不強制用c語言方式進行修飾,但是用stdcall約定,這種方式編譯產生的dll中有乙個匯出函式:?add@@yghhh@z。這個名字很怪,後面的不好理解。

四:宣告為:int __declspec(dllexport) __cdecl add(int x, int y);

這種宣告是不強制用c語言修飾,且用cdecl約定,這種方式編譯產生的dll中有乙個匯出函式:?add@@yahhh@z,注意看,和第三種方有一點不同。

實驗一:顯式呼叫方式呼叫dll中的add函式。

#include

#include

typedef  int(_stdcall *lpaddfun)(int, int); //巨集定義函式指標型別

int main(int argc, char *argv)

else

printf("no function");

} else

printf("no dll");

freelibrary(hdll);

return 0;

} 方式一:呼叫成功。另外三種方式全部出錯

實驗二:隱式呼叫dll中的add函式

#include

#include

#pragma comment(lib,"1.lib")

extern "c" int __declspec(dllimport) add(int x, int y);//宣告方式隨著dll中的宣告方式改變

int main(int argc, char *argv)

方式一:呼叫成功。另外發現乙個奇怪現象:在呼叫程式中

宣告函式時extern "c" int __declspec(dllimport) add(int x, int y);

寫作:extern "c" int __declspec(dllecprot) add(int x, int y);同樣成功,將__declspec(…)去掉也同樣成功。換句話說,在呼叫dll的程式中,匯入是沒有必要加的。

方式二:呼叫成功。同樣出現上面匯入標識可以不加的現象。

方式三:呼叫成功,同樣也出現上面匯入標識可以不加的現象。

方式四:呼叫成功,同樣也出現上面匯入標識可以不加的現象。

總結:對於dll匯出函式宣告的四種寫法,在動態呼叫時,

宣告成這樣:extern "c" int __declspec(dllimport) add(int x, int y);是最好的,其它宣告方式呼叫都沒有成功。但是眾所周知,windows預設的呼叫約定是stdcall方式,如果想別的語言能用dll的話,最好是將呼叫約定寫成stdcall方式,但是這種方式又不能動態呼叫。

在隱式呼叫時,四種宣告方式都是可以的,只要呼叫者的宣告方式和dll宣告時的方式一致即可。另外,在呼叫程式中對於匯入的宣告是可以去掉的,大量書籍中關於匯入、匯出的問題都是利用巨集來處理的,如:在標頭檔案中寫作:

#ifdef dll_file

extern "c" int __declspec(dllexport) add(int x, int y);

#else

extern "c" int __declspec(dlleximport) add(int x, int y);

這樣這個標頭檔案既可以用在dll工程中,又可以用在呼叫程式中,但是經過實驗發現,這個根本就沒有必要,在呼叫者程式中不管是寫作__declspce(dllexport)還是寫作__declspec(dllimport)或者不寫都能成功呼叫。

關於def檔案

在dll工程中引用def檔案,內容如下:

library 1

exports

add @ 1

通過depends檢視匯出函式全是add,但是隱式方式呼叫時,還是要求呼叫者的宣告方式和dll中宣告方式相同。

對於動態呼叫實驗結果:

方式一:成功。方式二:不成功,但是將函式指標改為typedef int(_stdcall *lpaddfun)(int, int);成功,即呼叫者要宣告約定方式與dll中宣告的呼叫約定方式相同,否則報錯。

方式三:同方式二,同樣要將函式指標改為typedef int(_stdcall *lpaddfun)(int, int);才成功完成呼叫。

方式四:成功。

總結:通過def檔案來匯出函式,呼叫者同樣也要宣告相同的呼叫約定,即_stdcall或是_cdecl必須要相同,其中_cdecl是c語言預設方式。

複習一下MSIL的一些問題

前陣子俺一直沉迷在遊戲和 中,最近玩累了。於是回過頭來,突然發現有些東西感覺就像抓不住的水一樣就要被淡忘了。也許是需要複習一下了,可不能把以前學的全忘光了 當然,以我的懶惰,所謂的複習也就 基本是隨興複習,沒什麼計畫的亂來了。msil和堆疊形影不離,兩者的關係就像手術室中的醫生和 醫生負責動手術 部...

移動支付遇到的一些問題彙總一下

話說好久不寫部落格,也是醉了.算了不提了.這兩天在弄支付寶,結果出來一大堆問題,比如不能跳轉支付介面,crash,記憶體洩露等等.現在成功了,感覺還是不錯的,把問題彙總一下,由於自己手法不好,大家別笑.公鑰私鑰這就不說了,官網有教程,照著來就行了 我的問題大多是plist檔案配置的問題 plist要...

c 一些問題總結

這裡總結一些c 常遇到的問題 不同型別之間的轉換。1 string const char std string s 1 lsw const char cs 1 s 1.c str printf const char cs is s n cs 1 2 const char string const c...