姐妹们你们睡过老外么:vb调用C++写的DLL
来源:百度文库 编辑:中财网 时间:2024/05/05 10:01:05
首先必须了解此函数在C中的原型,包括参数类型和传递方式。
C DLL 原型 VB声明 VB调用
int a ByVal a as long Call func(…,a,…)
long a ByRef a as long Call func(…,byval a,…)
int *pa ByRef pa as long Call func(…,pa,…)
long *pa ByVal pa as long Call func(…,varptr(pa),…) *(1)
char *pstr ByVal pstr as string Call func(…,pstr,…) *(2)
wchar *pstr ByRef pstr as string Call func(…,byval pstr,…)
struct tagX *p ByRef p as tagX Call func(…,ptag,…) *(3)
HANDLE h ByVal h as long Call func(…,h,…) *(4)
注意
1)不推荐使用此方式
2)如果DLL要求一个字符串缓冲区,一定要在调用前初始化字串,即dim t as string * 50
3)用户定义子类型必须用ByRef方式传递,
4)任何内核对象的句柄(process, thread, module, file, filemapping, semaphore等)和大多数GDI对象的句柄都能用此方式传递。
近日开发一个程序,用到动态链接库,在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文件首部用“#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文件放在“\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中调用,运行正常。
③关于调用约定
采用②中第二种解决方法,运行,出现错误信息“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;
}
④源代码
Cipher.dll:
Cipher.cpp:
//引入预编译头文件
#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:
LIBRARY Cipher
EXPORTS Encrypt
编译后,将Cipher.dll复制到“D:\WINNT\System32”目录。
在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
对该文的评论 人气:1077
gengdong (2004-4-26 21:25:05)
二,在Cipher.dll代码中在语句“__declspec(dllexport) int __stdcall Encrypt(int p, int k); ”前加上“extern "C " ”,编译后,用QuikView查看,函数名变为“_Encrypt”,之后再在VB声明中做相应调整即可。 //这里是不是错了,按我的笔记里和作者的意思,这里应该是__declspec(dllexport) int __cdecl Encrypt(int p, int k);
WindsonZhL (2004-2-25 11:56:56)
__stdcall 又叫“回调函数”,MFC 有宏: #define CALLBACK __stdcall #define WINAPI __stdcall #define WINAPIV __cdecl #define APIENTRY WINAPI #define APIPRIVATE __stdcall
WindsonZhL (2004-2-24 15:55:15)
补充说明: ①使用了 def 文件,就可以不加 extern "C " 了; ②QuikView.exe 是 Win2000 Server 系统自带的程序,装有其它系统的用户可用 VC 的 Depends 工具察看; ③http://www.onlinedown.net/soft/4975.htm 可下载 Quick View Plus ,开发商 stellent,最新版本 v8.0 在vb中使用vc编译的dll实例
关键字 在VB中使用VC编译的dll
18:07 2003-12-3
今天,仿照着书,我使用vc编了一个动态链接库(dll)--a.dll,然后将它复制到windows/system/目录下面,之后建立了一个vb程序,并在程序中声明了a.dll中的函数add(),实现两个整形数的加法运算。
实现过程如下:
一、建立dll
打开vc,创建一个基于API的DLL.
---- 1.在FILE- > NEW- > PROJECTS中选择 "WIN32 Dynamic-Link Library "在Project Name中输入 "a "按OK
---- 2.在FILE- > NEW- > FILES中选择C++ SOURCE FILE,在FILE中输入a.cpp,按OK
---- 3.在FILE- > NEW- > FILES中选择TEXT文件,在FILE中输入a.h,按OK
---- 4.在FILE- > NEW- > FILES中选择TEXT文件,在FILE中输入a.def,按OK
---- 5.源文件:
代码
//---------------------------
//a.cpp
#include < windows >
WINAPI int add(int a,int b)
{ return (a+b);
}
//---------------------------
//a.h
WINAPI int add(int a,int b);
//---------------------------
//a.def
LIBRARY "a ";指出DLL的名字
DESCRIPTION 'a Windows Dynamic Link Library '
;描述DLL的用途(此句可选)
EXPORTS add;导出函数的名字
------6.编译成a.dll
------7.将a.dll复制到windows/system/目录下面
二、建立vb程序
在form1中输入
代码
Option Explicit
Private Declare Function add Lib "a.dll " (ByVal a As Integer, ByVal b As Integer) As Integer
Private Sub Command1_Click()
Text3.Text = Str(add(Val(Text1.Text), Val(Text2.Text)))
End Sub
程序界面如下图:
我在编程过程中遇到的问题:
在将a.dll复制到程序目录下之后(此时我没有将a.dll复制到windows/system/目录下面),运行程序,结果报错!如下图:
后来我将a.dll复制到E:盘,将
代码
Private Declare Function add Lib "a.dll " (ByVal a As Integer, ByVal b As Integer) As Integer改为Private Declare Function add Lib "E:/a.dll " (ByVal a As Integer, ByVal b As Integer) As Integer
,再次运行程序,也成功了!
不知道这是什么原因,书上说通常调用DLL时所需的DLL文件必须位于以下三个目录之一:
(1)Windows的系统目录:\windows\system;
(2)DOS中path所指出的任何目录;
(3)程序所在的目录。
不知道我在满足第三个条件的情况下,为什么会出错?
=================================================
21:36 2003-12-3
今天晚上,我到图书馆去看书,终于明白了为什么下午的程序会出错了.
最主要的原因是因为按F5执行程序时,程序还是处于调试阶段,所以它找不
到a.dll,想到这里,我把程序MAKE为应用程序,终于一切正常了。真是感到很欣
慰~
C DLL 原型 VB声明 VB调用
int a ByVal a as long Call func(…,a,…)
long a ByRef a as long Call func(…,byval a,…)
int *pa ByRef pa as long Call func(…,pa,…)
long *pa ByVal pa as long Call func(…,varptr(pa),…) *(1)
char *pstr ByVal pstr as string Call func(…,pstr,…) *(2)
wchar *pstr ByRef pstr as string Call func(…,byval pstr,…)
struct tagX *p ByRef p as tagX Call func(…,ptag,…) *(3)
HANDLE h ByVal h as long Call func(…,h,…) *(4)
注意
1)不推荐使用此方式
2)如果DLL要求一个字符串缓冲区,一定要在调用前初始化字串,即dim t as string * 50
3)用户定义子类型必须用ByRef方式传递,
4)任何内核对象的句柄(process, thread, module, file, filemapping, semaphore等)和大多数GDI对象的句柄都能用此方式传递。
近日开发一个程序,用到动态链接库,在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文件首部用“#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文件放在“\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中调用,运行正常。
③关于调用约定
采用②中第二种解决方法,运行,出现错误信息“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;
}
④源代码
Cipher.dll:
Cipher.cpp:
//引入预编译头文件
#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:
LIBRARY Cipher
EXPORTS Encrypt
编译后,将Cipher.dll复制到“D:\WINNT\System32”目录。
在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
对该文的评论 人气:1077
gengdong (2004-4-26 21:25:05)
二,在Cipher.dll代码中在语句“__declspec(dllexport) int __stdcall Encrypt(int p, int k); ”前加上“extern "C " ”,编译后,用QuikView查看,函数名变为“_Encrypt”,之后再在VB声明中做相应调整即可。 //这里是不是错了,按我的笔记里和作者的意思,这里应该是__declspec(dllexport) int __cdecl Encrypt(int p, int k);
WindsonZhL (2004-2-25 11:56:56)
__stdcall 又叫“回调函数”,MFC 有宏: #define CALLBACK __stdcall #define WINAPI __stdcall #define WINAPIV __cdecl #define APIENTRY WINAPI #define APIPRIVATE __stdcall
WindsonZhL (2004-2-24 15:55:15)
补充说明: ①使用了 def 文件,就可以不加 extern "C " 了; ②QuikView.exe 是 Win2000 Server 系统自带的程序,装有其它系统的用户可用 VC 的 Depends 工具察看; ③http://www.onlinedown.net/soft/4975.htm 可下载 Quick View Plus ,开发商 stellent,最新版本 v8.0 在vb中使用vc编译的dll实例
关键字 在VB中使用VC编译的dll
18:07 2003-12-3
今天,仿照着书,我使用vc编了一个动态链接库(dll)--a.dll,然后将它复制到windows/system/目录下面,之后建立了一个vb程序,并在程序中声明了a.dll中的函数add(),实现两个整形数的加法运算。
实现过程如下:
一、建立dll
打开vc,创建一个基于API的DLL.
---- 1.在FILE- > NEW- > PROJECTS中选择 "WIN32 Dynamic-Link Library "在Project Name中输入 "a "按OK
---- 2.在FILE- > NEW- > FILES中选择C++ SOURCE FILE,在FILE中输入a.cpp,按OK
---- 3.在FILE- > NEW- > FILES中选择TEXT文件,在FILE中输入a.h,按OK
---- 4.在FILE- > NEW- > FILES中选择TEXT文件,在FILE中输入a.def,按OK
---- 5.源文件:
代码
//---------------------------
//a.cpp
#include < windows >
WINAPI int add(int a,int b)
{ return (a+b);
}
//---------------------------
//a.h
WINAPI int add(int a,int b);
//---------------------------
//a.def
LIBRARY "a ";指出DLL的名字
DESCRIPTION 'a Windows Dynamic Link Library '
;描述DLL的用途(此句可选)
EXPORTS add;导出函数的名字
------6.编译成a.dll
------7.将a.dll复制到windows/system/目录下面
二、建立vb程序
在form1中输入
代码
Option Explicit
Private Declare Function add Lib "a.dll " (ByVal a As Integer, ByVal b As Integer) As Integer
Private Sub Command1_Click()
Text3.Text = Str(add(Val(Text1.Text), Val(Text2.Text)))
End Sub
程序界面如下图:
我在编程过程中遇到的问题:
在将a.dll复制到程序目录下之后(此时我没有将a.dll复制到windows/system/目录下面),运行程序,结果报错!如下图:
后来我将a.dll复制到E:盘,将
代码
Private Declare Function add Lib "a.dll " (ByVal a As Integer, ByVal b As Integer) As Integer改为Private Declare Function add Lib "E:/a.dll " (ByVal a As Integer, ByVal b As Integer) As Integer
,再次运行程序,也成功了!
不知道这是什么原因,书上说通常调用DLL时所需的DLL文件必须位于以下三个目录之一:
(1)Windows的系统目录:\windows\system;
(2)DOS中path所指出的任何目录;
(3)程序所在的目录。
不知道我在满足第三个条件的情况下,为什么会出错?
=================================================
21:36 2003-12-3
今天晚上,我到图书馆去看书,终于明白了为什么下午的程序会出错了.
最主要的原因是因为按F5执行程序时,程序还是处于调试阶段,所以它找不
到a.dll,想到这里,我把程序MAKE为应用程序,终于一切正常了。真是感到很欣
慰~
VB调用VC写的DLL
vb中调用dll的问题。
vb调用dll出错
VB调用DLL
VB调用MFC DLL
vb.net如何引用C++写DLL文件?及函数的调用方法?
vb 如何调用自己写的DLL文件!请把代码发到我信箱里,要VB,和DLL的代码
vb 调用 C
vb 调用未注册dll
vb调用 dll 奇怪问题
如何在.NET中调用普通C++或C语言写的DLL的API函数
[求助]关于vb编制的.dll调用问题?
关于vb生成的dll无法调用问题(急!)
vb.net 中如何调用c++编写的dll文件
java怎样调用c写的服务?
VC调用Delphi写的dll的问题
ASP怎么调用C#写的DLL文件呢?
VB怎样调用DLL中的资源
VB 调用的问题
我用VB做一C/S架构的ERP,调用.dll文件,每次调用结束后任务管理器里进程不关,不占用CPU资源只占内存
用VFP写一个调用DLL(DELPHI写的)的DEMO要怎么写
用VB调用VC编写的DLL的参数传递问题
C++builder4创建及调用DLL
[VB]如何把调用API的DLL文件封装到EXE程序本身?