本文**於:http://topic.csdn.net/u/20090824/13/be972397-bec9-4f7f-910c-83e0d91bcbad.html
有關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語言預設方式。
Dll 匯出函式 引用Dll外部函式宣告
匯出函式 declspec dllexport int function 匯出類class declspec dllexport class1 引用dll函式宣告 declspec dllimport int function 解決不同編譯器名字改編的問題 在定義匯出函式時加上 extern c 大...
總結一下DLL宣告的一些問題
有關dll的問題現在資料很多,但是很多人寫dll時經常出現呼叫程式無法找到相關的匯出函式的問題,這裡主要的原因是dll在宣告時出的問題。在這裡主要有兩個問題,乙個是呼叫約定的問題,乙個是函式名修飾的問題,而這兩個問題又是相互影響的。一 宣告為 extern c int declspec dllexp...
DLL視窗的控制總結
1.dll子視窗的式樣必須設定為無框 borderstyle bsnone formstyle fsnormal 可以在dll.dpr中 控制 2.dll.dpr vardllscr tscreen varptr plongint begin screen scr frmdllform.top to...