作为一种简单易用的Windows开发环境,Visual Basic从一推出就受到了广大编程人员的欢迎。它使 程序员不必再直接面对纷繁复杂的Windows消息,而可以将精力主要集中在程序功能的实现上,大大提高了编程效率。但凡事有利必有弊。VB中高度的封装和模块化减轻了编程者的负担,同时也使开发人员失去了许多访问低层API函数和直接与Windows交互的机会。因此,相比而言,
vb应用程序的执行效率和功能比C/C++或Delphi生成的程序要差。为了解决这个
问题,在一个大型的VB开发应用中,直接调用Windows API函数几乎是不可避免的;同时,还有可能需 要
程序员自己用C/C++等开发一些动态连接库,用于在VB中调用。本文主要讨论在32位开发环 境Visual Basic 5.0中直接调用Windows 95 API函数或用户生成的32位动态连接库的方法 与规则。
Windows动态连接库是包含数据和函数的模块,可以被其它可执行文件(EXE、DLL、OCX 等)调用。动态连接库包含两种函数:输出(exported)函数和内部(internal)函数。输出函数可以被其它模块调用,而内部函数则只能在动态连接库内部使用。尽管动态连接库也能输出 数据,但实际上它的数据通常是只在内部使用的。使用动态连接库的优点是显而易见的。将应 用程序的一部分功能提取出来做成动态连接库,不但减小了主应用程序的大小,提高了程序 运行效率,还使它更加易于升级。多个应用
程序共享一个动态连接库还能有效地节省系统资 源。正因为如此,在Windows系统中,动态连接库得到了大量的使用。
一般来说,动态连接库都是以DLL为扩展名的文件,如Kernel32.dll、commdlg.dll等。但也有例外,如16位Windows的核心部件之一GDI.exe其实也是一个动态库。编写动态连接库的工具很多,如VisualC++、BorlandC++、Delphi等,具体方法可以参见相关文档。下面只以Visual C++5.0为例,介绍一下开发应用于VisualBasic5.0的动态连接库时应注意的问题(本文中所有涉及C/C++语言或编译环境的地方,都以VC5为例;所有涉及VisualBasic的地方都以VB5 为例)。
作为一种32位Windows应用程序的开发工具,VB5生成的exe文件自然也都是32位的,通常情况下也只能调用32位的动态连接库。但是,并不是所有的32位动态库都能被VB生成的exe 文件正确地识别。一般来说,自己编写用于VB应用
程序调用的动态连接库时,应注意以下几个方面的问题:
1、生成动态库时要使用__stdcall调用约定,而不能使用缺省的__cdecl调用约定;__stdcall 约定通常用于32位API函数的调用。
2、在VC5中的定义文件(.def)中,必须列出输出函数的函数名,以强制VC5系统将输出函数的装饰名(decoratedname)改成普通函数名;所谓装饰名是VC的编译器在编译过程中生成的输出函数名,它包含了用户定义的函数名、函数参数及函数所在的类等多方面的信息。由于在VC5中定义文件不是必需的,因此工程不包含定义文件时VC5就按自己的约定将用户定义的输出函数名修改成装饰名后放到输出函数列表中,这样的输出函数在VB生成的应用
程序中是不能正确调用的(除非声明时使用Alias子句)。因此需要增加一个.def文件,其中列出用户需要的函数名,以强制VC5不按装饰名进行输出。
3、VC5中的编译选项"结构成员对齐方式(structure member alignment)" 应设成4字节,其原因将在后文详细介绍。
4、由于在C中整型变量是4个字节,而VB中的整型变量依然只有2个字节,因此在C中声 明的整型(int)变量在VB中调用时要声明为长整型(long),而C中的短整型(short)在VB中则 要声明成整型(integer);下表针对最常用的C语言数据类型列出了与之等价的Visual Basic 类型(用于32位版本的Windows)。
C语言数据类型在VisualBasic中声明为调用时使用的表达