当前位置:文档之家› vb调用vc的dll

vb调用vc的dll

一般来说,VB和VC共同编程有3种方式:一种是VC生成DLL,在VB中调用DLL;一种是VC 生成ActiveX控件(.ocx),在VB中插入;还有一种是在VC中生成ActiveX Automation服务器,在VB中调用。

相对而言,第一种方法对VC编程者的要求最低,但要求你的伙伴进行配合,我推荐这种方法。

先说说VC++的编程。

首先在VC++中生成Win32 DLL工程。

在这个工程中添加几个函数供VB 用户调用。

一个DLL中的函数要想被VB调用,必须满足两个条件:一是调用方式为stdcall,另一个是必须是export的。

要做到第一条,只须在函数声明前加上__stdcall关键字。

如:short __stdcall sample(short nLen, short *buffer)要做到第二条,需要在*.def文件中加上如下的几行:EXPORTSsample @1这里的sample是你要在VB中调用的函数名,@1表示该函数在DLL中的编号,每个函数都不一样。

注意这里的函数名是区分大小写的。

至于你说的需要传递大量数据,可以这样做,在VB中用一个数组存放数据,然后将该数组的大小和地址传给VC(至于如何在VB中编程我会在下面介绍)。

就象上面的例子,nLen是数组大小,buffer是数组地址,有了这两条,你可以象使用VC的数组一样进行处理了。

至于输出图形,可以生成WMF或BMP格式,让VB调用。

不过,我认为也可以直接输出到视窗,只要VB将窗口的句柄hWnd和hDC以及视窗的绘图位置(VB和VC采用的坐标系必须一致才行)传给VC就行了。

而VB的AutoRedraw属性必须为False,在Paint事件中调用VC的绘图程序。

再谈谈VB的编程。

VB调用DLL的方法和调用Windows API的方法是一样的,一般在VB的书中有介绍。

对于上面一个例子,先要声明VC函数:Declare Function sample Lib "mydll.dll" (ByVal nLen As Integer, buffer As Integer) As Integer这里mydll.dll是你的dll的名字。

你可能已经注意到了两个参数的声明有所不同,第一个参数加上了ByVal。

规则是这样的:如果在VC中某个参数声明为指针和数组,就不加ByVal,否则都要加上ByVal。

在VB中调用这个函数采用这样的语法:sample 10, a(0)这里的a()数组是用来存放数据的,10为数组长度,这里的第二个参数不能是a(),而必须是要传递的数据中的第一个。

这是VB编程的关键。

下面在说几个可能遇到的问题。

一个问题是VB可能报告找不到dll,你可以把dll放到system目录下,并确保VB的Declare语句正确。

另一个问题是VB报告找不到需要的函数,这通常是因为在VC中*.def文件没设置。

第三种情况是VB告诉不能进行转换,这可能是在VC中没有加上__stdcall 关键字,也可能是VB和VC的参数类型不一致,注意在VC中int是4个字节(相当于VB的Long),而VB的Integer只有2个字节。

必须保证VB和VC的参数个数相同,所占字节数也一致。

最后一个要注意的问题是VC中绝对不能出现数组越界的情况,否则会导致VB程序崩溃。

VB中调用VC++开发的DLL再谈在VB中调用VC++开发的DLL再谈在VB中调用VC++开发的DLL近日开发一个程序,用到动态链接库,在VB中调用时遇到了一些问题。

我查了一些资料,也看了一下CSDN上的文章,感觉这些文章对在VB中调用VC++开发的DLL这一问题阐述得不够详细。

因此在我的问题得到解决之余,特为初接触DLL的朋友们写下这篇文章。

本文中关于调用约定的解决方法,也适用于解决其它编程语言之间DLL调用的兼容问题。

①关于DLL的创建与调用使用VC++的向导即可。

具体操作如下:打开菜单“File\New”→选择“Projects\Win32 Dynamic-Link Library”→选择“A simple 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 53)”。

出现这一错误的原因是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){int c = p + k;return c;}④源代码Cipher.dll:Cipher.cpp://引入预编译头文件#i nclude “stdafx.h”#define CIPHER_API __declspec(dllexport)//声明我的函数CIPHER_API 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:LIBRARY CipherEXPORTS Encrypt编译后,将Cipher.dll复制到VB程序可执行文件所在目录。

在VB中调用:Option ExplicitPrivate Declare Function Encrypt Lib “Cipher” (ByVal p As Long, ByVal k As Long) As LongPrivate Sub Form_Load()Dim c As Longc = Encrypt(24, 8)Text1.Text = cEnd Sub第一种类型:数值传递注意:在VB中,默认变量传递方式为ByRef为地址,而传递值就是用ByVal,还要注意在C++中,int类型的变量是32位的,在VB中要用long型变量来配合。

VC++部分:[cpp]view plaincopy1.extern"C" _declspec(dllexport) int __stdcall TestCalc(int source)2.{3.//AFX_MANAGE_STATE(AfxGetStaticModuleState());4.return(++source);5.}.def文件EXPORTS TestCalcVB部分声明:[vb]view plaincopy1.Private Declare Function TestCalc Lib"Dll.dll" (ByVal Source As Long) As Long调用:[vb]view plaincopy1.Dim Tint As Long2.Tint = TestCalc(45)3.MsgBox Tint, vbExclamation第二种类型:传递字符串,主要用于字符串返回或者处理。

相关主题