1制作好DLL之后,就可以用VB调用它,实现VB调用C程序。VB程序要使用DLL中的函数,首先必须要有特殊的声明,用Declare声明语句在窗体级或模块级或全局模块的代码声明段进行声明,将动态链接库中的函数声明到VB中,供VB程序调用。语句格式为:DeclareSub过程名Lib[Alias别名]([ByVal参数AS类型]),或为DeclareFunction函数名Lib[Alias别名]([ByVal参数AS类型])AS类型在声明中首先用Declare关键字表示声明DLL中的函数。在C语言中有的函数类型为VOID,它表示不具有返回值,则必须用关键字Sub将其声明成过程。有的函数具有返回值,则必须用关键字Function将其声明成函数,并且在声明语句的最后要用AS关键字指明函数返回值的类型。例如上面的ADD.DLL在VB中就可以声明为:DeclareFunctionADDLib“c:\ADD.dll”(ByValXASInteger,ByValYASInteger,ByValfileinasstring)ASInteger通过此声明语句将函数ADD声明到VB中,便可直接调用。2、dll文件中的函数好像是C语言写的,//函数名:int__stdcallGetMacNo(int*MacNo)//功能:获取卡机的卡机号(单机时)//参数:MacNo[0]-被读出的卡机号//返回值:0-成功,//2-PC接收超时,//3-应答错误dll的文件名是COMM232.dll函数的形参int*MacNo是指针吗?在VB中应该怎么声明和调用该函数?VB里也可以定义指针吗?问题补充:vb调用dll文件中的函数我是会的,但这儿的形参有一个星号才不知是怎么一回事,我是这样声明的对吗?PublicDeclareFunctionGetMacNoLibCOMM232.dll(ByValMacNoAsInteger)AsInteger又应该怎么调用呢?要先定义一个指针的变量再传给*MacNo还是要怎么做?都说了MacNo是被读出的卡机号,那么就是传址的了。dimlasintegerdimmasintegerl=GetMacNo(m)ifl=0thenlabel1.caption=卡机号:&melseifl=2thenmsgboxPC接收超时elseifl=3thenmsgbox应答错误endifWindows动态连接库是包含数据和函数的模块,可以被其它可执行文件(EXE、DLL、OCX等)调用。动态连接库包含两种函数:输出(exported)函数和内部(internal)函数。输出函数可以被其它模块调用,而内部函数则只能在动态连接库内部使用。尽管动态连接库也能输出数据,但实际上它的数据通常是只在内部使用的。使用动态连接库的优点是显而易见的。将应用程序的一部分功能提取出来做成动态连接库,不但减小了主应用程序的大小,提高了程序运行效率,还使它更加易于升级。多个应用程序共享一个动态连接库还能有效地节省系统资源。正因为如此,在Windows系统中,动态连接库得到了大量的使用。一般来说,动态连接库都是以DLL为扩展名的文件,如Kernel32.dll、commdlg.dll等。但也有例外,如16位Windows的核心部件之一GDI.exe其实也是一个动态库。编写动态连接库的工具很多,如VisualC++、BorlandC++、Delphi等,具体方法可以参见相关文档。下面只以VisualC++6.0为例,介绍一下开发应用于VisualBasic6.0的动态连接库时应注意的问题(本文中所有涉及C/C++语言或编译环境的地方,都以VC为例;所有涉及VisualBasic的地方都以VB为例)。作为一种32位Windows应用程序的开发工具,VB生成的exe文件自然也都是32位的,通常情况下也只能调用32位的动态连接库。但是,并不是所有的32位动态库都能被VB生成的exe文件正确地识别。一般来说,自己编写用于VB应用程序调用的动态连接库时,应注意以下几个方面的问题:1、生成动态库时要使用__stdcall调用约定,而不能使用缺省的__cdecl调用约定;__stdcall约定通常用于32位API函数的调用。2、在VC中的定义文件(.def)中,必须列出输出函数的函数名,以强制VC系统将输出函数的装饰名(decoratedname)改成普通函数名;所谓装饰名是VC的编译器在编译过程中生成的输出函数名,它包含了用户定义的函数名、函数参数及函数所在的类等多方面的信息。由于在VC中定义文件不是必需的,因此工程不包含定义文件时VC就按自己的约定将用户定义的输出函数名修改成装饰名后放到输出函数列表中,这样的输出函数在VB生成的应用程序中是不能正确调用的(除非声明时使用Alias子句)。因此需要增加一个.def文件,其中列出用户需要的函数名,以强制VC不按装饰名进行输出。3、VC中的编译选项结构成员对齐方式(structurememberalignment)应设成4字节,其原因将在后文详细介绍。4、由于在C中整型变量是4个字节,而VB中的整型变量依然只有2个字节,因此在C中声明的整型(int)变量在VB中调用时要声明为长整型(long),而C中的短整型(short)在VB中则要声明成整型(integer);下表针对最常用的C语言数据类型列出了与之等价的VisualBasic类型(用于32位版本的Windows)。C语言数据类型在VisualBasic中声明为调用时使用的表达式ATOMByValvariableAsInteger结果为Integer类型的表达式BOOLByValvariableAsLong结果为Long类型的表达式BYTEByValvariableAsByte结果为Byte类型的表达式CHARByValvariableAsByte结果为Byte类型的表达式COLORREFByValvariableAsLong结果为Long类型的表达式DWORDByValvariableAsLong结果为Long类型的表达式HWND,HDC,HMENUByValvariableAsLong结果为Long类型的表达式等Windows句柄INT,UINTByValvariableAsLong结果为Long类型的表达式LONGByValvariableAsLong结果为Long类型的表达式LPARAMByValvariableAsLong结果为Long类型的表达式LPDWORDvariableAsLong结果为Long类型的表达式LPINT,LPUINTvariableAsLong结果为Long类型的表达式LPRECTvariableAstype自定义类型的任意变量LPSTR,LPCSTRByValvariableAsString结果为String类型的表达式LPVOIDvariableAsAny任何变量(在传递字符串的时候使用ByVal)LPWORDvariableAsInteger结果为Integer类型的表达式LRESULTByValvariableAsLong结果为Long类型的表达式NULLAsAny或ByValNothing或ByValvariableAsLongByVal0&或VBNullStringSHORTByValvariableAsInteger结果为Integer类型的表达式VOIDSubprocedure不可用WORDByValvariableAsInteger结果为Integer类型的表达式WPARAMByValvariableAsLong结果为Long类型的表达式5、VB中进行32位动态库的声明时,函数名是大小写敏感的。在获得了需要的动态连接库之后,就可以在VB中进行调用了。但是,由于VB不能验证应用程序传递到动态连接库中的参数值是否正确,因此VB程序中大量的API调用可能会降低整个应用程序的稳定性,也会增加以后维护的难度。所以,决定在VB程序中直接调用API函数时要慎重,但适当的使用API调用确实能够有效地提高VB程序的性能。这之间的平衡需要编程人员根据实际情况来掌握。下面就具体介绍一下在VB中调用API函数时需要做的工作。要声明一个DLL过程,首先需要在代码窗口的通用(General)部分增加一个Declare语句。如果该过程返回一个值,应将其声明为Function:DeclareFunctionpublicnameLiblibname[Aliasalias][([[ByVal]variable[Astype][,[ByVal]variable[Astype]]...])]AsType如果过程没有返回值,可将其声明为Sub:DeclareSubpublicnameLiblibname[Aliasalias][([[ByVal]variable[Astype][,[ByVal]variable[Astype]]...])]缺省情况下,在标准模块中声明的DLL过程,可以在应用程序的任何地方调用它。在其它类型的模块中定义的DLL过程则是模块私有的,必须在它们前面声明Private关键字,以示区分。下面分别介绍声明语句的各个组成部分。(一)、指定动态库:Declare语句中的Lib子句用来告诉VisualBasic如何找到包含过程的.dll文件。如果引用的过程属于Windows核心库(User32、Kernel32或GDI32),则可以不包含文件扩展名,如:DeclareFunctionGetTickCountLibkernel32AliasGetTickCount()AsLong对于其它动态连接库,可以在Lib子句指定文件的路径:DeclareFunctionlzCopyLibc:\windows\lzexpand.dll_(ByValSAsInteger,ByValDAsInteger)AsLong如果未指定libname的路径,VisualBasic将按照下列顺序查找该文件:①.exe文件所在的目录②当前目录③Windows系统目录④Windows目录⑤Path环境变量中的目录下表中列出了常用的操作系统环境库文件。动态链接库描述Advapi32.dll高级API服务,支持大量的API(其中包括许多安全与注册方面的调用)Comdlg32.dll通用对话框API库Gdi32.dll图形设备接口API库Kernel32.dllWindows32位核心的API支持Lz32.dll32位压缩例程Mpr.dll多接口路由器库Netapi32.dll32位网络API库Shell32.dll32位ShellAPI库User32.dll用户接口例程库Version.dll版本库Winmm.dllWindows多媒体库Winspool.drv后台打印接口,包含后台打印API调用。对于Windows的系统API函数,可以利用VB提供的工具APIViewer查找某一函数及其相关数据结构和常数的声明,并复制到自己的程序中。(二)、使用别名:A.函数名是标准的名称Declare语句中的Alias子句是一个可选的部分,用户可以通过它所标识的别名对动态库中的函数进行引用。例如,在下面的语句中,声明了一个在VB中名为MyFunction的函数,而它在动态库Mydll.dll中最初的名字是MyFunctionX。PrivateDeclareFunctionMyFunctionLibMydll.dll_AliasMyFunctionX()AsLong需要注意的是,Alias子句中的函数名是大小写敏感的,也就是说,必须与函数在生成时的声明(如在C源文件中的声明)一致。这是因为32位动态库与16位动态库不同,其中的函数名是区分大小写的。同样道理,如果没有使用Alias子句,那么在Function(或Sub)后的函数名也是区分大小写的。通常在以下几种情况时需要使用Alias子句:A.处理使用字符串的系统WindowsAPI过程如果调用的系统WindowsAPI过程要使用字符串,那么声明语句中