再谈在VB中调用VC++开发的DLL
2008-05-01 05:03
471 查看
近日开发一个程序,用到动态链接库,在VB中调用时遇到了一些问题。我查了一些资料,也看了一下CSDN上的文章,感觉这些文章对在VB中调用VC++开发的DLL这一问题阐述得不够详细。因此在我的问题得到解决之余,特为初接触DLL的朋友们写下这篇文章。
本文中关于调用约定的解决方法,也适用于解决其它编程语言之间DLL调用的兼容问题。 ①关于[/b]DLL[/b]的创建与调用[/b][/b] 使用VC++的向导即可。具体操作如下:打开菜单“FileNew”→选择“ProjectsWin32 Dynamic-Link Library”→选择“A simple DLL project”即可。这时系统会自动生成3个文件:*.cpp,stdafx.cpp,stdafx.h。 之后将入口函数DLLMain()补充完整,再添加你自定义的函数的代码。如果你自定义的函数很多,可以将这些函数的声明部分统一写入一个头文件中。再在.cpp文件首部用“#include”语句引入这个头文件。注意函数声明前要加上“__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文件放在“WindowsSystem”或“WinNTSystem32”目录下,“Lib”后只写出DLL主文件名即可。具体的实例代码见④(修正后的,可直接运行)。 ②关于入口点[/b][/b] 如上编写Cipher.DLL,运行,出现错误信息“找不到DLL入口点(Error 53)”。出现这一错误的原因是C++编译器在编译时对函数名Encrypt作了修改。打开快速查看程序(D:WINNTSystem32ViewersQuikView.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中调用,运行正常。 ③关于调用约定[/b][/b] 采用②中第二种解决方法,运行,出现错误信息“DLL调用约定错误(Error 49)”。原因是调用约定共有4种方式:__fastcall、__pascal、__stdcall、__cdecl,VC++默认调用方式为__cdecl,而VB默认调用方式则为__stdcall。解决方法是,更改代码如下(限定调用方式): extern “C” __declspec(DLLexport) int __stdcall Encrypt(int p, int k); ………… int __stdcall Encrypt(int p, int k) { int c = p+k; return c; } ④源代码[/b][/b]Cipher.DLL[/b]:[/b][/b] Cipher.cpp[/b]:[/b][/b] //引入预编译头文件 #include “stdafx.h” //声明我的函数extern “C” __declspec(DLLexport) int __stdcall Encrypt( int p, int k ); //DLL入口函数 BOOL APIENTRY DLLMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } //我的函数 int __stdcall Encrypt ( int p, int k ) { int c = p + k ; return c ; } Cipher.def[/b]:[/b][/b] LIBRARY Cipher EXPORTS Encrypt 编译后,将[/b]Cipher.DLL[/b]复制到“[/b]D:WINNTSystem32[/b]”目录。[/b][/b]在[/b]VB[/b]中调用:[/b][/b] Option ExplicitPrivate 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
本文中关于调用约定的解决方法,也适用于解决其它编程语言之间DLL调用的兼容问题。 ①关于[/b]DLL[/b]的创建与调用[/b][/b] 使用VC++的向导即可。具体操作如下:打开菜单“FileNew”→选择“ProjectsWin32 Dynamic-Link Library”→选择“A simple DLL project”即可。这时系统会自动生成3个文件:*.cpp,stdafx.cpp,stdafx.h。 之后将入口函数DLLMain()补充完整,再添加你自定义的函数的代码。如果你自定义的函数很多,可以将这些函数的声明部分统一写入一个头文件中。再在.cpp文件首部用“#include”语句引入这个头文件。注意函数声明前要加上“__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文件放在“WindowsSystem”或“WinNTSystem32”目录下,“Lib”后只写出DLL主文件名即可。具体的实例代码见④(修正后的,可直接运行)。 ②关于入口点[/b][/b] 如上编写Cipher.DLL,运行,出现错误信息“找不到DLL入口点(Error 53)”。出现这一错误的原因是C++编译器在编译时对函数名Encrypt作了修改。打开快速查看程序(D:WINNTSystem32ViewersQuikView.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中调用,运行正常。 ③关于调用约定[/b][/b] 采用②中第二种解决方法,运行,出现错误信息“DLL调用约定错误(Error 49)”。原因是调用约定共有4种方式:__fastcall、__pascal、__stdcall、__cdecl,VC++默认调用方式为__cdecl,而VB默认调用方式则为__stdcall。解决方法是,更改代码如下(限定调用方式): extern “C” __declspec(DLLexport) int __stdcall Encrypt(int p, int k); ………… int __stdcall Encrypt(int p, int k) { int c = p+k; return c; } ④源代码[/b][/b]Cipher.DLL[/b]:[/b][/b] Cipher.cpp[/b]:[/b][/b] //引入预编译头文件 #include “stdafx.h” //声明我的函数extern “C” __declspec(DLLexport) int __stdcall Encrypt( int p, int k ); //DLL入口函数 BOOL APIENTRY DLLMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } //我的函数 int __stdcall Encrypt ( int p, int k ) { int c = p + k ; return c ; } Cipher.def[/b]:[/b][/b] LIBRARY Cipher EXPORTS Encrypt 编译后,将[/b]Cipher.DLL[/b]复制到“[/b]D:WINNTSystem32[/b]”目录。[/b][/b]在[/b]VB[/b]中调用:[/b][/b] Option ExplicitPrivate 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
相关文章推荐
- 用VC开发API形式的DLL给VB调用的范例
- 再谈在VB中调用VC++开发的DLL
- 在VB应用程序中调用VC环境下开发的DLL
- 用VC开发API形式的DLL给VB调用的范例
- VS2010开发——vc++项目编写DLL提供vb.net调用
- 再谈在VB中调用VC++开发的DLL
- 在VB应用程序中调用VC环境下开发的DLL
- 在VB应用程序中调用VC环境下开发的DLL
- 在VB应用程序中调用VC环境下开发的DLL
- VB中调用VC++开发的DLL
- 在非VS环境下C++ Builder,Delphi,VC,VB等调用C#开发的DLL的完整方法
- 在VB应用程序中调用VC环境下开发的DLL
- 再谈在VB中调用VC++开发的DLL
- 在VB应用程序中调用VC环境下开发的DLL
- 一步一步教你用VC和VB调用C++ DLL
- 在 VB 中调用 VC 写的 DLL
- cygwin跨平台移植开发系列2--so2lib实用工具(把cygwin生成的so或dll转换成vc可调用的lib)
- VB中调用VC的DLL
- 在 VB 中调用 VC 写的 DLL
- VB调用VC写的DLL导出函数出现“Bad DLL call convention”的解决