vb调用vc的dll
- 格式:doc
- 大小:94.50 KB
- 文档页数:17
VB调用C/C++编写的DLL函数说明2009-11-10 10:58:17| 分类:技术文摘| 标签:|举报|字号大中小订阅方法一:VB默认的传递方式就是传指针(ByRef,也就是把变量的地址传递给所调用的函数)。
如果要传值(也就是把变量的值传递给所调用的函数)反要在参数声明前加ByVal。
所以如果你传递的参数是普通的数据类型,在参数前什么都不要加就行了。
如C语言声明为:void __stdcall MyProc(short * nPara);则VB声明为:Declare Function MyProc Lib "MyDll.dll" (nPara As Integer)调用时同普通函数。
如果C语言中的指针是字符串指针,那么在VB声明时需要加上ByVal,这是个例外。
如C语言声明为:void __stdcall MyProc(char * sPara);则VB声明为:Declare Function MyProc Lib "MyDll.dll" (ByVal sPara As String)调用时同普通函数。
如果C语言的指针是数组指针,则在VB中调用时应将数组的首元素传递给DLL。
如C语言声明为:void __stdcall MyProc(int [] arrPara);则VB声明为:Declare Function MyProc Lib "MyDll.dll" (nPara As String)调用时为MyProc A(0)。
注意:不能直接传递数组名,因为如果传递数组名,VB实际会传一个复杂的结构类型给DLL,这对编写C语言的DLL来说,处理这样的结构比较麻烦,所以通常都不支持这种方式。
方法二:C++ 函数需要指针到C 函数或传递一个数组当从VisualBasic 数组传递到函数通常, 如果编写一个函数在 C 或C++, 中并且未明确旨在函数调用从VisualBasic, 函数需要指针指向第一个元素的数组。
VB调用VC创建的Win32 DLL函数
周振红;冯夏庭;杨国录;周洞汝
【期刊名称】《计算机工程》
【年(卷),期】2002(028)004
【摘要】探讨了Visual C++创建Win32DLL,Visual Basic对其函数实施调用过程中,命名修饰,调用约定、命名约定的匹配,数据类型对应以及参数传递一致性等问题,并给出了具体的应用实例.
【总页数】3页(P285-286,封三)
【作者】周振红;冯夏庭;杨国录;周洞汝
【作者单位】郑州大学水环学院,郑州,450002;中国科学院武汉岩土力学研究所,武汉,430071;武汉大学,武汉,430072;武汉大学,武汉,430072
【正文语种】中文
【中图分类】TP313
【相关文献】
1.VB调用VC创建的DLL及在控制领域中的应用 [J], 薛燕红
2.在VC中对Delphi所生成的DLLs的调用 [J], 李强;贾云霞
3.怎样在LabVIEW中调用Win32动态连接库(DLLs) [J], 陶以政;潘振显
4.PB调用VC创建的DLL在MIS中的设计与实现 [J], 陈建泗;商建云
5.在VB开发环境中调用由MATLAB函数转化的DLL [J], 冯旭
因版权原因,仅展示原文概要,查看原文内容请购买。
VB调用C程序的方法—动态链接库法文中介绍了一种实现VB调用C语言程序的方法-动态连接库法,给出了动态链接库制作的一般框架,通过实例描述了动态连接库的实现及其制做方法、编程步骤,这种方法具有普遍的意义。
关键词VB 动态连接库DLL C程序一、引言Visual Basic( 以下简称VB)是一种可视化的面向对象的编程语言,以其编程简单、快捷等特点,深受广大WINDOWS程序员的青睐。
利用VB开发界面友好、操作方便的软件只需很短的时间。
但是VB运行速度较慢,对于庞大的科学计算问题,VB的这种慢速会使人难以忍受。
C语言是国际上非常流行的一种中级编程语言,以其灵活、高效等优点而获得广泛应用,许多的应用程序都是用C语言在DOS环境下编写而成。
那么如何发挥VB和C这两种语言的优势,用VB设计一种良好的for windows界面来调用C语言程序,即实现VB调用C 语言程序呢?现有的文献只提到动态链接库(以下简称DLL)可以将这两种语言连接起来,但有讲动态链接库DLL的制做及其编程方法。
本文详细介绍了Borland C环境下制作动态链接库以及VB调用for dos动态链接库的的方法、步骤,并通过实例描述VB调用C程序的全过程。
二、用Borland C编写DLL程序的方法要想实现VB调用C程序,首先需要用Borland C编写动态连接库DLL程序(假设DLL程序取名为example)。
动态链接库包含四个文件:C语言源程序(.C)、模块定义文件(.DEF)、原型函数文件(.H)和工程文件(.PRJ)。
下面分别详细介绍一下这四种文件的具体结构。
1、编写C语言源程序的框架:C语言源程序(example.C),它包括三种函数:入口函数、输出函数和终止函数。
其具体结构如下:/*************************************//* 文件名:example.C *//*************************************/#include <windows.h>/***********入口函数***********/int FAR PASCAL LibMain ( HANDLE hInstance,WORD wDataSeg,WORD cbHeapSize,LPSTR lpszCmdLine ){if (cbHeapSize!=0)UnlockData(0);return (1);}/***********输出函数***********/int FAR PASCAL example(int param1,...,char param n){...... /*C语言应用程序*/}/***********终止函数***********/int FAR PASCAL WEP ( int /*SystemExit*/ ){return(1);}以上各组成部分参数的含义:Windows.h头文件,它包含有数据类型的定义、API入口点定义和其它有用的参数信息。
利用vc6.0编写DLL文件,为了方便其他函数调用,可以采取以下方式方法过程一采用Win32 Dynamic-Link Library建立。
过程:本次采用建立一个计算整数的平方和立方的plf.dll文件。
1文件—新建—工程—Win32 Dynamic-Link Library,工程名称为plf,点击确定,后选择一个空白文档。
2,点击做下角FileView。
显示如图1所示2.左上角文件—新建—文件—C++ Source File,输入名称为plf.,建立空白文档plf.cpp在其内输入代码如图2所示:3左上角文件—新建—文件—C++ Header File,输入名称为plf.,建立空白文档plf.h在其内输入代码如图3所示:4在plf文件夹中新件文本文档,里面输入如图4所示代码保存,改后缀名为def.名称为plf.def。
5 右击Source Files,选中添加文件到目录,对话框选中plf.def文件。
6点击组建(plf.dll)或者直接键盘F7。
7打开DEBUG文件夹中有两个文件为plf.dll和plf.lib文件,保留。
三验证1 使用vc验证建立vc源程序,输入代码为2 采用vb验证其中关键是语句Public Class Form1Private Declare Function sq Lib"D:\vcb\plf\plf.dll" (ByVal i As Integer) As IntegerPrivate Declare Function cub Lib"D:\vcb\plf\plf.dll" (ByVal j As Integer) AsInteger。
【转】vb调用dll函数声明方法用vc写的DLL的有__stdcall才可以被其他的调用,所以。
vb调用16 位DLL 调用方法与32 位DLL 调用方法类同。
语法:[Public | Private] Declare Fun Function name Lib "li bname" [Alias "aliasname"]ction [([arglist])] [As type]Declare 语句的语法包含下面部分:Public 可选的。
用于声明对所有模块中的所有其它过程都可以使用的函数。
Private 可选的。
用于声明只能在包含该声明的模块中使用的函数。
name 必需的。
任何合法的函数名。
动态链接库的入口处(entry points)区分大小写。
libname 必需的。
包含所声明的函数动态链接库名或代码资源名。
Alias 可选的。
表示将被调用的函数在动态链接库(DLL) 中还有另外的名称。
当外部函数名与某个函数重名时,就可以使用这个参数。
当动态链接库的函数与同一范围内的公用变量、常数或任何其它过程的名称相同时,也可以使用Alias。
如果该动态链接库函数中的某个字符不符合动态链接库的命名约定时,也可以使用Alias。
aliasname 可选的。
动态链接库。
如果首字符不是数字符号(#),则aliasname 是动态链接库中该函数的入口处的名称。
如果首字符是(#),则随后的字符必须指定该函数的入口处的顺序号。
arglist 可选的。
代表调用该函数时需要传递的参数的变量表。
type可选的。
Function 返回值的数据类型;可以是Byte、Boolean、Integer、Long、Currency、Single、Double、Decimal (目前尚不支持)、Date、String(只支持变长)或Variant,用户定义类型,或对象类型。
arglist 参数的语法以及语法各个部分如下:[Optional] [ByVal | ByRe ByRef] [ParamArray] varnam e[( )] [As type] 部分描述:Optional可选的。
VB调用C程序的方法动态链接库法
VB(Visual Basic)和C(C语言)是两种不同的编程语言,两
者的编译和语言规则不同,但是它们之间是可以相互调用的。
在VB
程序中,可以通过调用C程序实现更加复杂的功能。
方法一:动态链接库
动态链接库(Dynamic Link Library,简称DLL)是一种可以
被多个程序共享的程序库,它可以为不同的程序提供相同的功能,
这意味着它可以被VB程序以及其他程序调用。
VB程序可以使用Windows API来加载和调用DLL文件中的函数,而C程序可以通过
导入、导出关键字来将函数导出为DLL文件中的函数,从而被VB程
序调用。
在VB程序中,调用C程序所在的DLL文件中的函数,步骤如下:
1. 在VB程序中进行声明,指定要调用的函数名、返回类型和
传入参数。
例如:
```
Declare Function MyFunction Lib \
1。
VB6.0调用C# Dll文件总结VB6.0调用C# Dll文件总结在工作中遇到了在VB6.0的程序里要调用C#的Dll的问题,显然这两个开发环境属于不同的平台。
在网上拜读了几位大师的文章后,在实际试验中还是会发生这样那样的问题,最后还是实现了预期效果,在此我把我的实验步骤和注意事项分享如下,希望对需要之人有所帮助:实验环境:C#dll的创建使用的是VS2008;VB6.0一、C#部分1.用C#创建一个ClassLibrary项目(VS2008);2.所有在VB6中要使用的方法都必须通过继承接口实现,并且为public的(非常重要,没有继承接口实现的方法,在VB6.0里面无法调用);3.接口和类都需要加入属性Guid;Guid通过VS2008自带的工具得到:4.在VS2008的DOS命令工具提示框中运行:sn -k C:\myKey.snk<回车>在C盘根目录下生成一个强名称文件:myKey.snk(注意这个强名称文件的名字可以自己定义,我暂定为myKey.snk)5. 右击项目,选择属性,打开并编辑项目的属性对话框在Application tab中,点击Assembly Information按钮,在打开的对话框中选中“make Assembly COM-Visible”(重要)在Build Tab中,最好用Release模式编译,确认选中“Make assembly COM-Visible”(重要)。
在Signing Tab中引入上一步创建的强名称文件myKey.snk6. 检查项目的AssemblyInfo文件,ComVisible应设为true,项目和文件版本不为1.0.*,应该是一个具体的值;7.编译这个项目,生成dll文件。
到此为止,C#的Dll部分已经准备完毕了。
二、VB6部分1. VB6调用环境必须安装.Net framework2.0或以上版本,最好是3.5(和VS2008相同的framework);2. 复制dll文件进入VB6环境的目标文件夹,例如D:根目录,D:\TestCom.dll3. 在Dos命令窗口用regasm命令注册这个dll文件生成.tlb 文件regasm D:\TestCom.dll /tlb:D:\TestCom.tlb /codebase在D:\将会生成一个TestCom.tlb文件4.在Dos命令窗口用gacutil命令添加Dll文件到GAC中(全局程序集缓存),这样这个Dll文件在这个PC中就可以随处使用gacutil /I D:\TestCom.dll5.在VB6项目中,把生成的.tlb文件加入到项目(References)6. VB6代码即可调用tlb文件Private Sub Command1_Click()Dim obj As New t0426a.Class1bel1.Caption = obj.GetString()End Sub注意:以上3,4步,需要在VB6环境的C:\WINDOWS\system32下面有相应的exe文件才可运行;第4步,可以省去;还要说明的是,当转移这个VB6生成的exe程序(这个VB6可执行文件引用了C#的dll)到另外一台电脑上的时候,需要把这个C# Dll文件一同Copy到那台电脑上,并且重新执行第3步的注册生成tlb文件的工作,否则这个exe程序无法运行。
VB6中如何访问C#Dll中的方法、属性以及事件一个简单的例子实现VB6中访问C# dll中的方法、属性以及事件。
C# DLL1) 要使得C# dll中的方法、属性以及事件在VB6中暴露出来,以便写代码方便,需要加入相应的接口- 方法和属性的接口,本例中为IComInterOpClass[Guid("12A7D9AE-B42F-4a91-9EEE-5E0951A552E2")][InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]public interface IComInterOpClass{//Methodstring SayHello();//Propertystring Name { get; set; }}- 事件的接口,本例中为IComInterOpEvent[Guid("868FD423-2504-4f5c-AB47-9F2B7DB8ED2C")][InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispat ch)]public interface IComInterOpEvent{void EventTest(string msg);}2) 实现部分,注意事件的接口不需要继承,它是以Attribute的方式加入的。
本例中的事件是用timer实现5秒钟触发一次。
namespace ComInterOpLibrary{public delegate void EventTestHandler(string message);[Guid("BA6DF62E-D59E-4e46-B2E6-F1CD990A1E18")][ClassInterface(ClassInterfaceType.None)][ComSourceInterfacesAttribute("ComInterOpLibrary.IComIn terOpEvent")][ProgId("ComInterOpClass")]public class ComInterOpClass : IComInterOpClass{private Timer myTimer = null;//Eventpublic event EventTestHandler EventTest;//Propertypublic string Name { get; set; }public ComInterOpClass(){myTimer = new Timer(5000);myTimer.AutoReset = true;myTimer.Enabled = true;myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);}void myTimer_Elapsed(object sender, ElapsedEventArgs e) {if (EventTest != null){EventTest("Good day!");}#region IComInterOpClass Members//Methodpublic string SayHello(){return"Hello " + Name;}#endregion}}3) 至此,C# dll部分就完成了,最后记得将项目的Register for COM InterOp选上。
一般来说,VB和VC共同编程有3种方式:一种是VC生成DLL,在VB中调用DLL;一种是VC 生成ActiveX控件(.ocx),在VB中插入;还有一种是在VC中生成ActiveX Automation服务器,在VB中调用。
相对而言,第一种方法对VC编程者的要求最低,但要求你的伙伴进行配合,我推荐这种方法。
先说说VC++的编程。
首先在VC++中生成Win32 DLL工程。
在这个工程中添加几个函数供VB 用户调用。
一个DLL中的函数要想被VB调用,必须满足两个条件:一是调用方式为stdcall,另一个是必须是export的。
要做到第一条,只须在函数声明前加上__stdcall关键字。
如:short __stdcall sample(short nLen, short *buffer)要做到第二条,需要在*.def文件中加上如下的几行:EXPORTSsample @1这里的sample是你要在VB中调用的函数名,@1表示该函数在DLL中的编号,每个函数都不一样。
注意这里的函数名是区分大小写的。
至于你说的需要传递大量数据,可以这样做,在VB中用一个数组存放数据,然后将该数组的大小和地址传给VC(至于如何在VB中编程我会在下面介绍)。
就象上面的例子,nLen是数组大小,buffer是数组地址,有了这两条,你可以象使用VC的数组一样进行处理了。
至于输出图形,可以生成WMF或BMP格式,让VB调用。
不过,我认为也可以直接输出到视窗,只要VB将窗口的句柄hWnd和hDC以及视窗的绘图位置(VB和VC采用的坐标系必须一致才行)传给VC就行了。
而VB的AutoRedraw属性必须为False,在Paint事件中调用VC的绘图程序。
再谈谈VB的编程。
VB调用DLL的方法和调用Windows API的方法是一样的,一般在VB的书中有介绍。
对于上面一个例子,先要声明VC函数:Declare Function sample Lib "mydll.dll" (ByVal nLen As Integer, buffer As Integer) As Integer这里mydll.dll是你的dll的名字。
你可能已经注意到了两个参数的声明有所不同,第一个参数加上了ByVal。
规则是这样的:如果在VC中某个参数声明为指针和数组,就不加ByVal,否则都要加上ByVal。
在VB中调用这个函数采用这样的语法:sample 10, a(0)这里的a()数组是用来存放数据的,10为数组长度,这里的第二个参数不能是a(),而必须是要传递的数据中的第一个。
这是VB编程的关键。
下面在说几个可能遇到的问题。
一个问题是VB可能报告找不到dll,你可以把dll放到system目录下,并确保VB的Declare语句正确。
另一个问题是VB报告找不到需要的函数,这通常是因为在VC中*.def文件没设置。
第三种情况是VB告诉不能进行转换,这可能是在VC中没有加上__stdcall 关键字,也可能是VB和VC的参数类型不一致,注意在VC中int是4个字节(相当于VB的Long),而VB的Integer只有2个字节。
必须保证VB和VC的参数个数相同,所占字节数也一致。
最后一个要注意的问题是VC中绝对不能出现数组越界的情况,否则会导致VB程序崩溃。
VB中调用VC++开发的DLL再谈在VB中调用VC++开发的DLL再谈在VB中调用VC++开发的DLL近日开发一个程序,用到动态链接库,在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文件首部用“#i nclude”语句引入这个头文件。
注意函数声明前要加上“__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中调用,运行正常。
注意使用了.def文件,就不需要再使用“extern "C" ”了。
③关于调用约定采用②中第二种解决方法,运行,出现错误信息“DLL调用约定错误(Error 49)”。
原因是调用约定共有5种方式:__fastcall、__pascal、__stdcall、__cdecl及__thiscall(成员函数的调用方式,但不能使用它显示声明一个函数),VC++默认调用方式为__cdecl,而VB默认调用方式则为__stdcall。
解决方法是,更改代码如下(指定调用方式):__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://引入预编译头文件#i nclude “stdafx.h”#define CIPHER_API __declspec(dllexport)//声明我的函数CIPHER_API 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 CipherEXPORTS Encrypt编译后,将Cipher.dll复制到VB程序可执行文件所在目录。
在VB中调用:Option ExplicitPrivate Declare Function Encrypt Lib “Cipher” (ByVal p As Long, ByVal k As Long) As LongPrivate Sub Form_Load()Dim c As Longc = Encrypt(24, 8)Text1.Text = cEnd Sub第一种类型:数值传递注意:在VB中,默认变量传递方式为ByRef为地址,而传递值就是用ByVal,还要注意在C++中,int类型的变量是32位的,在VB中要用long型变量来配合。
VC++部分:[cpp]view plaincopy1.extern"C" _declspec(dllexport) int __stdcall TestCalc(int source)2.{3.//AFX_MANAGE_STATE(AfxGetStaticModuleState());4.return(++source);5.}.def文件EXPORTS TestCalcVB部分声明:[vb]view plaincopy1.Private Declare Function TestCalc Lib"Dll.dll" (ByVal Source As Long) As Long调用:[vb]view plaincopy1.Dim Tint As Long2.Tint = TestCalc(45)3.MsgBox Tint, vbExclamation第二种类型:传递字符串,主要用于字符串返回或者处理。