vc.dll,vc6.0调用dll
大一学的是C,然后大二上了C的课程,然后自学了一些VC。大三的时候,我试着写了MFC最简单的窗口程序。大四的时候又做了一个GIS项目,是用C#.NET写的,后来发现C#很好用,大部分语法规则都沿袭了C和C的习惯,感觉C根本没有优势。但是这个暑假的实习经历改变了我的观点:C虽然写窗口程序麻烦,但是什么也做不了,而且和C#相比,不需要安装100M以上的running。NET环境,然后再安装C#程序。C#和C#各有优缺点。目前我对他们的定位是:用C写一些底层的程序,比如驱动,或者一些算法类型的函数接口,然后用C #调用这些接口,设计接口。如何实现跨语言的功能?显然,DLL是一个非常重要的内容,所以这里介绍一下VC的DLL模块。
用VC创建DLL动态连接库
1.1创建dll项目
然后选择“一个空的dll项目”,点击“确定”完成“创建dll项目”的过程。
1.2为dll项目编写源文件
创建了两个新文件:dllDemo.h和dllDemo.cpp
在头文件“dllDemo.h”中声明三个接口函数:
extern C _ declspec(dll export)int Sum(int a,int b);//加法功能。extern C _ declspec(dll export)int Max(int a,int b);//取值较大的函数extern c _ declspec(dll export)int min(int a,int b);//具有较小值的函数
然后,在“dllDemo.cpp”文件中实现了三个接口函数:
#include dllDemo.h
extern C _ declspec(dll export)int Sum(int a,int b)
{
返回a b;
}
extern C _ declspec(dll export)int Max(int a,int b)
{
if(a=b)返回a;
其他
返回b;
}
extern C _ declspec(dll export)int Min(int a,int b)
{
if(a=b)返回b;
其他
返回a;
}
1.3生成dll文件
编译源文件。如果没有错误提示,将在项目文件根目录的Debug文件夹中生成一个dll文件“dllDemo.dll”。
2 DLL调用
2.1用c调用显式链接
为显式调用创建新的Win32控制台程序:
1.创建一个新的Win32控制台程序项目“dllConsoleEvident”
2.创建一个新的cpp文件“dllConsoleEvident.cpp”
3.将第一节调试目录中编译的“dllDemo.dll”文件(显式调用时只需要这个文件)复制到“dllConsoleEvident”项目下的调试文件夹的根目录下。
4.在“dllConsoleEvident.cpp”文件中编写以下代码,以显式调用dll中的函数
//动态加载DLL文件
#包含iostream.h
#包含windows.h
无效总管(无效)
{
typedef int(*pMax)(int a,int b);//函数指针
typedef int(*pMin)(int a,int b);
pMax Max=NULL
pMin Min=NULL
HINSTANCE hDLL
hDLL=LoadLibrary( mydll . dll );//加载动态链接库MyDll.dll文件;
Max=(pMax)GetProcAddress(hDLL, Max );
Min=(pMin)GetProcAddress(hDLL, Min );
If (Max)//如果提取函数成功,执行下面的语句
{
int A=Max(5,8);
cout 比较的结果是 a;
}
if(分钟)
{
int B=Min(5,8);
cout’比较的结果是‘b;
}
免费图书馆(hDLL);//卸载MyDll.dll文件;
}
2.2与c (Win32控制台程序)的隐式链接
创建一个新的Win32控制台程序来演示静态调用。
1.使用向导创建一个空项目“dllConsoleStaticDemo”
2.将“dllDemo.dll”和“dllDemo.lib”文件复制到调试目录,并将“dllDemo.lib”文件(或)包含在项目中,否则会出现dll函数找不到的连接错误。
3.创建一个新的“dllConsoleStaticDemo.cpp”文件,并编写以下代码:
extern C _ declspec(dllimport)int Sum(int a,int b);
extern C _ declspec(dllimport)int Max(int a,int b);
extern C _ declspec(dllimport)int Min(int a,int b);
#包含iostream.h
void main()
{
int c=Sum(4,5);
c=Max(5,6);
c=Min(5,6);
cout 你好,dllConsoleTest ~!;
}
4.通过断点,可以看到dll函数被成功调用。
这种方式静态调用的特点是,所有的dll文件都会在程序执行之初加载到程序中,而不会被释放。
2.3与c (MFC窗口程序)的隐式链接
创建一个新的MFC基本对话框窗口程序来调用:
1.使用向导建立MFC basic对话框。
2.将“dllDemo.dll”和“dllDemo.lib”文件复制到这个项目的调试目录下,将“dllDemo.lib”添加到VC工作区的文件视图下的项目中。
3.在头文件“dllMfcDemoDlg.h”的前面从外部声明dll函数
//dllMfcDemoDlg.h:头文件
//
#如果
# define AFX _ DLLMFCDEMODLG _ H _ _ e358b 876 _ D188 _ 48FD _ 8d 83 _ 794309 c885a 9 _ _ INCLUDED _
# VER国际机场1000
#杂注一次
#endif //_MSC_VER 1000
/////////////////////////////////////////////////////////////////////////////
//CDllMfcDemoDlg对话框
extern C _ declspec(dllimport)int Sum(int a,int b);
extern C _ declspec(dllimport)int Max(int a,int b);
extern C _ declspec(dllimport)int Min(int a,int b);
……
4.在窗口界面,双击“确定”按钮,进入OnOk()的事件响应函数体,编写调用代码:
void CDllMfcDemoDlg:OnOK()
{
//TODO:在此添加额外的验证
int c=Sum(4,5);
c=Max(5,6);
c=Min(5,6);
CDialog:OnOK();
}
可以看到,通过设置断点,一步运行,dll文件中的函数已经被成功调用。
2.4用C#进行跨语言调用
# C控制台程序调用VC构建一个dll:
1.用Visual Studio建立控制台程序
2.将“dllDemo.dll”文件复制到项目的调试目录中。
3.在“Program.cs”中编写以下代码
使用系统;
使用系统。集合。泛型;
使用系统。文本;
使用系统。Runtime . InteropServices//在dll文件中引入函数
命名空间控制台lDemo
{
班级计划
{
//在dll文件中引入函数
[DllImport(dllDemo.dll)]
私有静态extern int Sum(int a,int b);
[DllImport(dllDemo.dll)]
private static extern int Max(int a,int b);
[DllImport(dllDemo.dll)]
private static extern int Min(int a,int b);
静态void Main(string[] args)
{
int a=Sum(3,5);
控制台。WriteLine(a);
控制台。WriteLine(Max(5,10));
控制台。WriteLine(Min(12,25));
控制台。read key();//按键退出。
}
}
}
然后断点一步运行,可以看到调用函数的结果。
3 dll调试方法
dll项目建立后,编写相应的实现代码,点击“运行”,弹出当前对话框:
然后浏览找到一个可执行文件“*”。然后在断点处调试该dll文件。
这个“*。exe”文件可以是任何平台的,C、C或C#,只要这个可执行文件调用dll文件中的函数。
如果你想改变被调试的" *。exe”文件,可以在项目-设置对话框的调试选项卡上设置,浏览找到“*。exe”文件。
注意:以在VC环境下调用这个dll为例,运行dllDemo项目,然后调用“*。exe”文件。如果这个exe文件包含一个源文件,而且就在源文件的调试目录下面,那么你可以同时在exe文件的源文件中设置一个断点,进行dll和调用dll的联合调试。(看来跨语言调用是无法调试的。作者只在C调用对方时调试成功,C#调用时没有调试成功。这个问题需要解决。)
4.DLL返回的数据类型探讨
目前DLL函数的反向返回值只限于整形,其他特殊类型的返回值还没有尝试过。丰富的返回值类型,还要以后慢慢学习和研究。