必威注册电子书籍教程中心网文荟萃客户留言繁體中文
设为首页
加入收藏
联系必威注册
您当前的位置:92动力网 -> 教程中心 -> 编程经验 -> Visual Basic -> 教程内容 退出登录 用户管理
栏目导航
· Visual Basic· Delphi
· Visual C++· C++ Builder
· JAVA DotNet· 其他相关
热门教程
· 如何在Visual Basic...
· 使用Visual Basic操...
· 使用VB6.0设计Activ...
· VB动态调用外部函数...
· 建立一个程序员自己...
· 如何编写高质量的VB...
· [图文] 为更新到Visual Bas...
· 再谈在VB中调用VC++...
· 用VB语言编程实现JP...
· 用DTS实现SQL数据库...
相关教程
· 让自己编写的DLL加载...
· 在C#中使用C/C++写的...
· [图文] Crystal Report(水晶...
· 让你的.NET程序兼容...
· 揪出系统中胡作非为...
· 揪出隐藏在背后的DL...

再谈在VB中调用VC++开发的DLL
作者:佚名聽聽来源:本站整理聽聽发布时间:2005-12-25 18:57:19聽聽发布人:admin

减小字体 增大字体

  近日开发一个程序,用到动态链接库,在VB中调用时遇到了一些问题。我查了一些资料,也看了一下CSDN上的文章,感觉这些文章对在VB中调用VC++开发的DLL这一问题阐述得不够详细。因此在我的问题得到解决之余,特为初接触DLL的朋友们写下这篇文章。

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

  ①关于DLL的创建与调用

  使用VC++的向导即可。具体操作如下:打开菜单“FileNew”→选择“ProjectsWin32 Dynamic-Link Library”→选择“A simple DLL project”即可。这时系统会自动生成3个文件:*.cppstdafx.cppstdafx.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主文件名即可。

具体的实例代码见④(修正后的,可直接运行)。 

  ②关于入口点

  如上编写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中调用,运行正常。

  ③关于调用约定

  采用②中第二种解决方法,运行,出现错误信息“DLL调用约定错误(Error 49)”。原因是调用约定共有4种方式:__fastcall__pascal__stdcall__cdeclVC++默认调用方式为__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,

聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 DWORDul_reason_for_call,

聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽LPVOID lpReserved

聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽)

聽聽聽聽聽聽 {

聽聽聽聽聽聽聽聽聽聽聽switch( ul_reason_for_call )

聽聽聽聽聽 聽聽聽聽 {

聽聽聽聽聽聽聽聽聽聽聽聽 case DLL_PROCESS_ATTACH:

聽聽聽聽聽聽聽聽聽聽聽聽 caseDLL_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:WINNTSystem32”目录。

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


[] [返回上一页] [打 印] [收 藏]
∷相关教程评论∷    (评论内容只代表网友观点,与本站立场无关!) [更多评论...]
关于本站 - 网站帮助 - 广告合作 - 下载声明 - 网站地图 - 管理登录
Copyright 2019 必威注册. All Rights Reserved .
浙ICP备05047688号