① 關於dll的建立與呼叫使用vc++的嚮導即可。具體操作如下:開啟選單「file\new」→選擇「projects\win32 dynamic-link library」→選擇「a ****** dll project」即可。這時系統會自動生成3個檔案:*.cpp,stdafx.cpp,stdafx.h。
之後將入口函式dllmain()補充完整,再新增你自定義的函式的**。如果你自定義的函式很多,可以將這些函式的宣告部分統一寫入乙個標頭檔案中。再在.cpp檔案首部用「#i nclude」語句引入這個標頭檔案。注意函式宣告前要加上「__declspec(dllexport)」。
(如果你建dll時選擇的是第三種型別(加入示例**),則在函式宣告及定義前都要加上系統定義的巨集「*_api」。)
在vb中用如下語句宣告:「declare function 函式名 lib "完整路徑\檔名.dll" [alias "函式別名"] (byval 變數1 as 型別1, byval 變數2 as 型別2,…) as 型別3」,與呼叫api函式類似。
注意:若在窗體**的「通用」部分使用,「declare」前要加「private」;若在moudle中使用,「declare」前要加「public」。若將dll檔案放在系統目錄(「\windows\system」或「\winnt\system32」)或程式可執行檔案所在目錄下,「lib」後只寫出dll主檔名即可。
具體的例項**見④(修正後的,可直接執行)。
② 關於入口點
如上編寫cipher.dll,執行,出現錯誤資訊「找不到dll入口點(error 453)」在除錯中耗費1.5天時間在網上找資料解決此問題。
網上指出可能原因:
1。沒有注意函式名大小寫。dll中的函式與vb中的函式宣告必須大小寫完全相同。
2。沒有宣告入口函式。需要在dll的.def檔案中加上入口函式。
如:exports
setdata @1
getdata @2
如果dll工程原本沒有使用.def檔案,可以自己建立乙個加入到工程中。
3。採用了c++編譯方式
在c++中編譯函式時會將函式名進行轉換。解決的方法有兩個:
(1)如果沒有使用c++的類,可以將.cpp檔案改名為.c,就不進行這種轉換了。
(2)在函式定義前加上extern "c",如:
extern "c" void _stdcall kk(double k)
需要指出的是,vc++允許不編寫.def檔案,而是在函式定義前加
_declspec(dllexport)修飾符,這樣的函式也可以被外部程式呼叫。
實際問題所在:(.def是關鍵)
排查完上面可能存在的問題後,
發現vb呼叫時依舊是「找不到dll入口點」
檢視vc程式結構,發現編譯時沒有將.def檔案載入進工程裡面。
這就導致生成的dll檔案沒有外部介面。總結自己還是vc不熟悉所致。
出現這一錯誤的原因是c++編譯器在編譯時對函式名encrypt作了修改。開啟快速檢視程式(d:\winnt\system32\viewers\quikview.exe),將cipher.dll拖入檢視視窗,找到字段「?encrypt@@yahhh@z」,發現函式名被加了一串字元。
解決方法有二。第一,直接在vb宣告中將「?encrypt@@y ahhh@z」作為別名放在「alias」後即可;第二,在cipher.dll**中在語句「__declspec(dllexport) int __stdcall encrypt(int p, int k);」前加上「extern "c" 」,編譯後,用quikview檢視,函式名變為「_encrypt」,之後再在vb宣告中做相應調整即可。
(對於使用巨集的dll,在「#define」語句中,對巨集「cipher_api」的替換值做更改即可。)
進行了③的更改後,程式又找不到入口點了。再用quikview檢視,發現函式名變為「_encrypt@8」。還有解決方法。在cipher.dll工程中新增乙個文字檔案,命名為「cipher.def」,新增**如④。編譯後再用quikview檢視,函式名變回「encrypt」,在vb中呼叫,執行正常。注意使用了.def檔案,就不需要再使用「extern "c" 」了。
③ 關於呼叫約定
採用②中第二種解決方法,執行,出現錯誤資訊「dll呼叫約定錯誤(error 49)」。
原因是呼叫約定共有5種方式:__fastcall、__pascal、__stdcall、__cdecl及__thiscall(成員函式的呼叫方式,但不能使用它顯示宣告乙個函式),vc++預設呼叫方式為__cdecl,而vb預設呼叫方式則為__stdcall。
解決方法是,更改**如下(指定呼叫方式):
__declspec(dllexport) int __stdcall encrypt(int p, int k);
…多個函式…
int __stdcall encrypt(int p, int k)
④ 源**
cipher.dll:
cipher.cpp內容:
//引入預編譯標頭檔案 __declspec(dllexport)是關鍵
#include 「stdafx.h」
#define cipher_api__declspec(dllexport)//巨集替換功能
//宣告我的函式
cipher_api int __stdcall encrypt( int p, int k )
………… 多個函式…
以上兩條語句等價於:
__declspec(dllexport) int __stdcall encrypt(int p, int k);
//dll入口函式 (實驗過可選)
bool apientry dllmain(handle hmodule,
dword ul_reason_for_call,
lpvoid lpreserved)
return true;
}//我的函式__stdcall關鍵
int __stdcall encrypt(int p, int k)
…多個函式…
…………………
//我的問題:沒有將.def檔案加入工程,導致生成的dll檔案呼叫函式沒有入口點
cipher.def:
library cipher
exports encrypt
編譯後,將cipher.dll複製到vb程式可執行檔案所在目錄。
也可以在呼叫時輸入乙個完整的路徑。
在vb中呼叫:
option explicit
private declare function encrypt lib 「cipher」 (byval p as long, byval k as long) as long
private sub form_load()
dim c as long
c = encrypt(24, 8)
text1.text = c
end sub
VB呼叫VC DLL的引數問題
問題示例如下,假設vb中申明乙個dll中的匯出函式為 public declare function somefunc lib test.dll alias somefunc byval name as string as long 那麼vc做的dll中的匯出函式原型是什麼?因為vb中的string...
關於C 呼叫VC DLL
由於在c 呼叫vc的dll檔案不能直接引用,那麼,我們可以通過以下辦法解決。dll檔案分為託管和非託管,在呼叫託管的很好辦,直接被使用的需要引用,間接使用的需要拷貝到bin目錄下.非託管的處理會比較麻煩,實際上,你拷貝到bin沒有任何幫助,因為clr會把檔案拷貝到乙個臨時目錄下,然後在那執行web,...
C 呼叫VC dll輸出引數
最近做專案需要把以前vc寫的程式整合到vs2005來,用c 寫的,以前vc的動態連線庫寫好了,重寫比較麻煩,讓c 呼叫vc dll就好了。但碰到了乙個問題 vc中作為輸出引數的char 型別的變數應該怎樣申明才能正確輸出資料呢?一般說來,在vc中一般的輸出引數都為指標或陣列的形式,如果是一般型別的指...