通过使用类型库提高VB调用DLL函数的性能

原创 2003年01月16日 08:53:00

 
本文始发于水木清华BBS(smth.org),转载请保留有关信息,谢谢! 


通过使用类型库提高VB调用DLL函数的性能


RoachCock@smth 
mailto:chen3feng@163.com,
chen3fengx@163.com,
chen3fengx@hotmail.com
 
VB虽然是个很好玩的东西,但是自身功能有限,限制了VB在某些方面的应用.
MS提供了两种两种方式来增强VB的功能,一种是调用COM组件,另一种就是调用Dll函数
 
说到调用COM,大家都很熟悉,在Project->Reference或者Project->Component
菜单弹出对话框中选择需要的类型库或者ActiveX控件,就可以把它加入Project.
 
调用Dll函数也很简单,需要使用Declare函数声明先:
Declare Function MessageBox Lib "user32" Alias "MessageBoxA" ( _
ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, _
ByVal wType As Long) As Long
 
然后就可以像内部函数一样调用了:
MessageBox Me.hWnd, "hehe", "Test", 0
 
下面我分析一下在上面的调用过程中,到底发生了什么.
 
我们知道,VB的字符串是Unicode字符串,每个字符占两个字节,但是翻开WinUser.h
我们可以看到MessageBoxA的真实定义,
WINUSERAPI int WINAPI MessageBoxA(HWND hWnd ,LPCSTR lpText,
 LPCSTR lpCaption, UINT uType);
 
LPCSTR是一个const char *类型,是一个指向单字节ANSI字符串的指针,
把调用这个函数的Project编译成exe,文件,用VC带的depends.exe看到底到如何引用的函数
 
竟然除了MSVBVM60.dll.什么也没有!
 
这中间到底发生了什么呢?
 
通过反汇编跟踪生成的代码可以知道,VB要先调用__vbaStrToAnsi把字符串转化成ANSI字
符串,再把得到的Ansi字符串传给一个内部函数(一般称为DllFunctionCall),这个函数再
真正去调用Dll中的函数
 
如果函数调用后还要使用传给Dll函数的字符串参数的话(比如GetWindowText什么的),就
更复杂了,VB编译器会调用一个叫做__vbaStrToUnicode的函数,把参数转化成Unicode,再
传递给函数.
 
也许你会说,MessageBox并不会改变传给它的参数,根本不需要在转换成Unicode.是的,你
知道,我也知道但是VB编译器不知道,声明函数的Declare语句里可没指出参数传递的方向.
 
也许你会说,我的程序只在WinNT,Win2K,WinXP下运行,他们内部都是用的Unicode字符串
,我直接调用Unicode版本的MessageBoxW不是更好吗?
 
对不起,由于Win9x只基本完全实现了ANSI函数,而基本没有实现Unicode版本的函数,而W
inNT则两者都实现了.为了照顾Win9x,VB把声明语句中的String都当成ANSI字符串.
//需要Unicode,却依赖于ANSI操作系统,可怜的VB!
 
由此,我想你已经看到了Declare语句到底在那里影响了效率.好吧.让我们开始新的历程
!
 
[idl语言和类型库]
类型库对VB程序员来说应该很熟悉了,这里我只简单的介绍一下idl语言.
IDL (Interface Definition Language)是主要用于COM和CORBA的一种接口定义语言,用
来描述各种接口,只是一种描述语言而不是一种编程语言.IDL的风格类似于C.IDL语言不
但可以描述更多的数据类型还可以描述参数的传递方向,因此上面的两个问题都不再是问
题了.
 
一般使用IDL语言都是为了描述COM接口等.其实IDL也一样可以用于描述全局函数.让我们
看一个例子,
 
还举那个MessageBox吧
 
打开VC6,新建一个Utitity Project,名字就叫MyTlb吧
新建一个文本文件,名字还叫MyTlb.idl吧,输入以下内容:
 
[ // 方括号表示一个idl属性,用来描述一些额外的信息,要和下面的东西连起来看.
 uuid("9F7B1BC0-28C6-11d7-8F56-0080C8F0A08C") // 用VC带的GUidgen生成一个新的
GUID,别和我的这个一样哦
]
library MyLib // library说明了一个类型库,MyLib是库的名字
{
 
 [
  dllname("user32.dll") file://因为下面的模块描述了函数,所以需要dll库的名字
 ]
 module Test // test是模块的名字
 {
  [
   entry("MessageBoxW") // entry属性表明下面函数的入口,可以是函数的名字或者序号
  ]
  long __stdcall Message(HWND hWnd, [in]LPCWSTR msg, [in]LPCWSTR title, long
 flags);
  // __stdcall表示函数的调用约定,后面是参数表
  // [in]表示参数只传入,[out][in]表示参数只传入,[in,out]表示既传入又传出,类推
 
  // 对于简单的值类型,可以省略,默认就是[in]了
  // 再有函数可以接着写
 }
}
 
按F7编译,一个崭新的类型库诞生了! // btw,直接调用midl编译器也可以,不过我觉得很
多人都不喜欢命令行了, :)
 
把它引入我们的工程,不需要声明直接就可以调用MessageBox了.反汇编代码,可以发现没
有多余的转换.
 
而且因为明确的指出了参数传递方向,不需要假设参数会被改变,生成的代码会更高效,
避免了DllFunctionCall的开支,更节省时间.

 
其他函数也可以一样处理,Windows 98 Resource Kit带了一个Win.tlb,包含了常用Wind
ows类型,常量,以及API的定义,非常方便,完全可以摆脱Declared语句的使用.可以在天网
(http://e.pku.edu.cn)搜到.
 
不过这个tlb是ANSI版本的(WIn98嘛),如果需要Unicode版本的,就得自己写idl文件编译

 
至于其他不带类型库的的DLL函数,你可以找这上面的例子自己来,函数数目比较多的情况
下完全划的来.
 
祝各位假期编程愉快!
 
--
 

通过使用类型库提高VB调用DLL函数的性能

  • zgqtxwd
  • zgqtxwd
  • 2008年05月01日 05:42
  • 111

VB调用c++写的Dll的一点总结

最近,写了一个VB应用程序,这个APP主要是用来演示三个C++写的视频处理动态链接库的使用方式。第一次写VB的代码,确实遇到了很多问题,现在回想一下,真的是很多东西走了或多或少的弯路,现在把这些东西总...
  • emma_he
  • emma_he
  • 2008年10月06日 17:36
  • 8550

VB封装DLL实例(一)

正 文: 一、  DLL基本概念 (一)概念 DLL即动态链接库(Dynamic Link Library),是由可被其它程序调用的函数集合组成的可执行文件模块。DLL不是应用程序的组成部分,而是运行...
  • miaoyangzhi
  • miaoyangzhi
  • 2017年02月11日 17:30
  • 561

VB如何调用DLL

Windows动态连接库是包含数据和函数的模块,可以被其它可执行文件(EXE、DLL、OCX 等)调用。动态连接库包含两种函数:输出(exported)函数和内部(internal)函数。输出函数可...
  • u013408061
  • u013408061
  • 2014年04月21日 16:09
  • 2913

vb调用C#写的dll

在做系统升级维护的项目中,用到了老系统(VB实现)要调用一部分新功能(C#实现)的情况,于是进行了简单的调查。发现如下资料网上发现的资料。-------------------------------...
  • smallboy_5
  • smallboy_5
  • 2008年10月01日 16:47
  • 13598

VB6.0调用DLL

目 录 第1章 VB6.0调用DLL    1 1 VC++编写DLL    1 1.1 使用__stdcall    1 1.2 使用 .DEF 文件 ...
  • Hanford
  • Hanford
  • 2016年12月10日 16:25
  • 2446

VB中调用VC++开发的DLL

转自:http://lanshanlhy.blog.163.com/blog/static/302294762010112832031218/ 再谈在VB中调用VC++开发的DLL  再谈...
  • xl19900502
  • xl19900502
  • 2016年02月22日 11:17
  • 594

如何用VB,C#调用C++写的DLL

之前在网上搜集了一些资料,现在稍微gkg
  • shejiannan
  • shejiannan
  • 2014年05月19日 16:18
  • 1371

如何用VB编写自己的DLL文件,并调用其中的函数

如何用VB编写自己的DLL文件,并调用其中的函数?
  • sillyboy1104
  • sillyboy1104
  • 2015年03月09日 22:54
  • 2908

如何调用dll文件中的函数

动态链接主要是利用LoadLibrary、GetProcAddress、FreeLibrary这三个api。 LoadLibrary HINSTANCE LoadLibrary(LPC...
  • q5512049
  • q5512049
  • 2015年07月30日 14:14
  • 992
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:通过使用类型库提高VB调用DLL函数的性能
举报原因:
原因补充:

(最多只允许输入30个字)