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调用C程序的方法―动态链接库法【摘要】本文将介绍VB调用C程序的方法―动态链接库法。
我们将解释动态链接库的概念以及如何在VB中使用动态链接库调用C程序。
接着我们会详细讲解如何创建动态链接库和在VB中调用动态链接库的步骤。
在最后的注意事项中,我们将强调一些需要注意的细节和技巧。
结论部分将强调VB调用C程序的方法的重要性,并讨论未来的发展方向。
通过本文,读者将了解如何利用动态链接库实现VB和C程序之间的无缝衔接,为软件开发提供更多可能性。
VB调用C程序的方法―动态链接库法在软件开发中扮演着重要的角色,其未来发展方向也值得我们深入探讨。
【关键词】VB调用C程序、动态链接库、概念、使用、创建、调用、注意事项、重要性、未来发展方向1. 引言1.1 VB调用C程序的方法―动态链接库法VB调用C程序的方法―动态链接库法是一种常见且高效的方法,用于实现不同编程语言之间的互操作性。
动态链接库(Dynamic Link Library,简称DLL)是一种共享库,其中包含了可被程序动态调用的函数和资源。
在VB中调用C程序,可以通过创建动态链接库来实现。
首先需要编写一个C程序,并将其编译为动态链接库。
然后在VB中通过声明函数的方式引用这个动态链接库,就可以直接调用其中的函数了。
这样可以充分利用C程序的高性能和灵活性,实现与VB的无缝集成。
需要注意的是,在使用动态链接库时要确保函数的参数和返回值的类型与VB中的数据类型兼容。
要避免内存泄漏等问题,需要注意内存的分配和释放。
VB调用C程序的方法―动态链接库法对于提高程序的性能和扩展功能具有重要意义。
未来可以进一步完善这种方法,提供更加方便快捷的方式实现跨语言调用,促进不同语言之间的交流和合作。
VB调用C 程序的方法―动态链接库法将在跨平台开发和系统集成方面发挥越来越重要的作用。
2. 正文2.1 动态链接库的概念动态链接库(Dynamic Link Library,简称DLL)是一种可被多个程序同时使用的程序代码和数据的集合,它可以在运行时被载入内存,并由多个进程共享。
4.1 新建工程打开在VC++6.0,new一个Win32-Dynamic-Link Library工程dlltest。
4。
2 在工程中添加代码4.2。
1添加lib。
h文件:#ifndef _LIB_H_#define _LIB_H_extern “C" int __stdcall add(int,int);extern “C” int __stdcall sub(int,int);/*__stdcall 约定如果通过VC++ 编写的DLL 欲被其他语言编写的程序调用,应将函数的调用方式声明为__stdcall 方式,WINAPI 都采用这种方式,而C/C++缺省的调用方式却为__cdecl。
__stdcall 方式与__cdecl 对函数名最终生成符号的方式不同*/#endif4。
2.2添加lib。
cpp文件:#include “lib。
h”int __stdcall add(int a,int b){return a+b ;}int __stdcall sub(int a,int b){return a-b ;}4.2.3添加lib.def文件:右击SOURCE FILE目录,添加一个文本文件(不能是word文档,一般是txt格式的),将文档重命名为lib.def,点击打开该文档。
在文档中输入代码:LILBRARY dlltestEXPORTSadd @ 1sub @ 2说明:DLL函数的导出有两种方式。
一种是显式导出:在.h文件中在函数声明前加入如下语句:__declspec(dllexport)。
使用该方法是不用添加。
def文档的。
该方法导出的函数,只能被C或C++调用,不能被其他语言调用.一种是隐式导出:就是在SOURCE FILE目录中添加一个。
def文档,在该文档中写入要导出函数的代码。
def语法规定注释用分号(;),且注释不能与代码共享一行,代码说明如下:LIBRARY dlltest;该语句说明了相应的DLL工程。
如何实现VB和VC的联合调试我用VC写了一个DLL,然后用VB写EXE。
我现在想调试我的DLL和EXE,在VB环境下调试,可是我无法跳入DLL函数的内部,无法在DLL内部调试。
有没有一个办法能让我实现VB和VC联调,当我在VB环境中需要跳入DLL函数时,进入VC环境,在VC中调试,这样我就可以查看变量值、设置断点,然后等函数返回时又回到VB环境下继续调试。
后来经过我自己的一番摸索,终于实现了VB、VC联调。
这个方法是以VC为主环境,VB为副环境,这是因为DLL是由VC编写的,而在调试DLL的时候一般会让我们指定一个EXE。
如果DLL是VB编写的,我想应该是以VB为主环境(没有测试过)。
1.建立一个VB Standard EXE工程project1.vbp,在这个工程中调用VC编写的动态连接库中的函数。
2.建立一个VC DLL工程TestDll,编写代码实现函数输出。
建议把整个工程目录放置到project1.vbp 所在的目录。
3.设置VC工程,这一步是非常重要的,是实现联调的关键。
a) 更改General选项卡中OutPut Files的路径,指定到project1.vbp所在的目录。
由于我把工程目录放在了project1.vbp目录下,因此我这里用相对路径“..\”(其实就是project1.vbp所在的目录)。
b) 更改Debug选项卡中Executable for debug session:为你电脑中VB6.exe;更改Working directory为project1.vbp所在的目录;在Program arguments:中填写project1.vbp,这个参数其实是传给VB的,让VB打开project1.vbp,如果增加参数”/r”,那么在VB启动后立即开始(相当于按F5),如果不增加参数”/r”,那么需要手动开始。
c) 确认你的Link选项卡中输出DLL的路径及DLL名称,把他设定到project1.vbp所在的目录:4.在你的DLL源程序(VC中)中设定断点,按F5, GO!怎么样,VB环境已经运行起来了,工程project1.vbp 已经打开了吧!如果你在3)b.的Program arguments:中指定了”/r”参数,那么这个时候程序已经开始运行了,如果你没有指定这个参数,那么你可以先在VB环境中设定断点,然后在调用DLL函数上设置断点,按F5,Start!如果在VB中遇到断点,程序就会停下,然后按F8,Step into! 发现什么了,哈哈,VC环境主动切换到前面,而且当前的箭头已经指向了被调用函数了,这个时候,已经进入VC环境了,你想怎么调试都可以!当被调用函数要结束时,请按F11,Step Out,否则会有一段汇编代码。
分享如何在VB中调⽤VC编写的DLL⼀般来说,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的名字。
1制作好DLL之后,就可以用VB调用它,实现VB调用C程序。
VB程序要使用DLL中的函数,首先必须要有特殊的声明,用Declare声明语句在窗体级或模块级或全局模块的代码声明段进行声明,将动态链接库中的函数声明到VB中,供VB程序调用。
语句格式为:Declare Sub过程名Lib[Alias"别名]([ByVal参数AS类型]),或为Declare Function函数名Lib[Alias"别名]([ByVal参数AS类型])AS类型在声明中首先用Declare 关键字表示声明DLL中的函数。
在C语言中有的函数类型为VOID,它表示不具有返回值,则必须用关键字Sub将其声明成过程。
有的函数具有返回值,则必须用关键字Function将其声明成函数,并且在声明语句的最后要用AS关键字指明函数返回值的类型。
例如上面的ADD.DLL在VB中就可以声明为:Declare Function ADD Lib“c:\ADD.dll”(ByVal X AS Integer,ByVal Y AS Integer,ByVal filein asstring)AS Integer通过此声明语句将函数ADD声明到VB中,便可直接调用。
2、dll文件中的函数好像是C语言写的,//函数名:int__stdcall GetMacNo(int*MacNo)//功能:获取卡机的卡机号(单机时)//参数:MacNo[0]-被读出的卡机号//返回值:0-成功,//2-PC接收超时,//3-应答错误dll的文件名是COMM232.dll函数的形参int*MacNo是指针吗?在VB中应该怎么声明和调用该函数?VB里也可以定义指针吗?问题补充:vb调用dll文件中的函数我是会的,但这儿的形参有一个星号才不知是怎么一回事,我是这样声明的对吗?Public Declare Function GetMacNo Lib"COMM232.dll"(ByVal MacNo As Integer)As Integer又应该怎么调用呢?要先定义一个指针的变量再传给*MacNo还是要怎么做?都说了MacNo是被读出的卡机号,那么就是传址的了。
Step by Step: Calling C++ DLLs from VC++ and VB 一步一步教你用VC和VB挪用C++ DLL.本系列教程讨论了一般情形下4种利用DLL的方式从VC++应用程序调用C++ DLL的函数Part 1从VC++应用程序调用C++ DLL的类从VB应用程序调用C++ DLL的函数从VB应用程序调用C++ DLL的类从VC++应用程序动态的调用C++ DLL的函数从VC++应用程序挪用C++ DLL的函数Visual Studio 6 使创建包括函数或类的动态连接库(DLL) 变得超级容易。
第一步:打开Visual Studio 然后选择File | New菜单项:选择Win32 Dynamic Link Library, 输入工程名, 敲OK.选择A DLL that exports some symbols并单击Finish.在File View里你会看到如下的工程文件:第二步在里,你将看到如下代码:TEST_API int fnTest(void){return42;}果你此刻编译, 你将会取得一个能够被其他VC++应用程序直接挪用的DLL.许诺其他VC++程序挪用的关键机制?( key mechanism)就包括在中:All files within this DLL#ifdef TEST_EXPORTS#define TEST_API __declspec(dllexport)#else#define TEST_API __declspec(dllimport)#endif};extern TEST_API int nTest;TEST_API int fnTest(void);那个地址面发生了什么? #ifdef TEST_EXPORTS是什么意思? TEST_EXPORTS又是在哪概念的?TEST_EXPORTS若是被概念, 那么TEST_API将会被概念为__declspec(dllexport) (DLL导出),不然,将会被概念为__declspec(dllimport)(DLL导入). 这将阻碍到后边概念的Ctest 类是导出类仍是导入类. 这意味着若是咱们需要导出的时候,咱们就得概念TEST_EXPORTS.当一个VC++应用程序要访问那个DLL的时候,能够将链接进去,它包括了DLL的导出符号.第三步:TEST_EXPORTS在哪里被概念了呢? DLL wizard干了一件我讨厌的事,它把TEST_EXPORTS 放到了命令行里. 选择Project | Settings | C/C++ | General,你将看到工程选然了,那个方法是可行的. 可是它却容易让人忽计,而且可能致使保护上的麻烦. 我比较喜爱清楚明白的概念TEST_EXPORTS : 从项目选项里边去掉/D "TEST_EXPORTS",然后在里来概念它:..注意#define TEST_EXPORTS在#include ""前边. 因此,它概念要在头文件里.此刻,能够像先前那样从头编译咱们的, 咱们将取得一个能够被其他VC应用程序所挪用的DLL.第四步咱们如何挪用DLL里的函数呢? 举个例子吧, 我用VS创建一个例如. 选MFC AppWizard (exe),输入项目名字,然后点OK. 选择基于对话框. 然后点Finish.打开(XXX是你的工程名字.) 找到OnInitDialog()成员函数, 敲进去如下的代码:...The framework does this automatically..第六步若是你想赶时刻做一个演示的话, 你可能会尝试只是拷贝DLL的到你的项目目录里去,那么编译器会找到它. 但是当项目很大的时候,这可不是个好主意, 因为当你更新你的DLL文件时,可能会遇上危险.比如忘了拷贝它到你的exe的目录中去.这里有个简单的方法来解决这个问题: 选择Project | Settings | C/C++ | Settings | Preprocessor, 而且添加Additional include directories: (DLL工程的目录)提示:如此做事实上是假设DLL项目和EXE项目拥有同一个项目目录.此刻当我编译的时候, 我取得了一个linker errors!!Deleting intermediate files and output files for project 'TestExe - Win32 Debug'. --------------------Configuration: TestExe - Win32 Debug-------------------- Compiling resources...Compiling...Compiling...Generating Code...Linking...: error LNK2001: unresolved external symbol "__declspec(dllimport)public: __thiscall CTest::CTest(void)" (__imp_??0CTest@@QAE@XZ): error LNK2001: unresolved external symbol "__declspec(dllimport)int __cdecl fnTest(void)" (__imp_?fnTest@@YAHXZ)Debug/ : fatal error LNK1120: 2 unresolved externalsError executing .- 3 error(s), 0 warning(s)第七步尽管我已经告知编译器DLL符号啦,可是链接器还不明白. 因此咱们必需告知链接器.. 选择Project | Settings | Link,把DLL的lib文件加到Object/library modules里边去:第八步好啦,此刻编译通过. 在咱们运行程序前,别忘了一件事: 把拷贝到EXE的目录里去.第九步接下来,能够放一个断点到OnInitDialog()函数里去, 点GO(F5)调试运行:能够看到, fnTest返回了42, 和咱们预测的一样. CTest类也能够用类似的方式来测试.要点:•VS的工程向导为咱们创建VC++DLL提供了专门好的开始.••函数,类, 和变量能够从DLL中导出.••利用#define预处置器概念, 一个头文件将能够被DLL 和应用程序一起利用.••DLL导出它的符号,而且应用程序导入那个DLL符号. 当编译应用程序时,编译器通过头文件看到的DLL符号, 当链接应用程序时, 链接器通过导入库看到DLL符号.••当执行应用程序时,DLL必需放到和EXE相同的目录中去. DLL也能够放到windows或system目录中,如此也是可行的, 可是它常常引发某些问题, 因此应该幸免如此利用注释:再实际工作中,我很少用到第七步中的方式. 如此做的话,在大的工程中,DLL和Lib文件将常常变得很难治理.咱们会想到要成立一个lib目录和一个bin目录,在那个地址边放进去所有咱们要利用的lib文件, dll文件和exe文件. 若是如此做的话,咱们怎么告知链接器找到lib文件呢? 有两种方式来做:1.选择Tools | Options | Directories and set Show directories for为"Library files". 在下边添加上咱们工程所利用的Lib文件的途径.2. 另一种方法是,选择Project | Settings | Link, 选category为Input ,在下边的Additional library path 筐里输入工程利用的lib文件的所在途径.哪一种方式更好一点呢?这取决于你的开发环境. 第一种方式要求整个工程要共享的设置目录途径, 而且所有要求所有的开发者的VS都必需设置到这些途径.第二种方式许诺每一个工程定制自己的途径,而且在工程中被贮存,若是开发者的运算机上寄存了一样的目录,那么每一个开发者都能够签出工程而且设计. ,如此能够幸免在每台机械上都去设置一样的途径.到此刻,我尚未说如何指定要利用的LIB文件, 我的方法是在DLL的中添加两行,此刻它看起来像下边的样子:#ifdef TEST_EXPORTS#define TEST_API __declspec(dllexport)#else#define TEST_API __declspec(dllimport)#pragma message("automatic link to ")。
一般来说,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第二种类型:传递字符串,主要用于字符串返回或者处理。