视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
VC++的DLL应用(含Demo演示)
2025-09-25 14:22:24 责编:小OO
文档
VC++的DLL应用(含Demo演示)

2010-11-21 下午 11:29

     在大学大一的时候学的是C,然后后来大二的时候专业又开了C++这个课程,然后再后来自己又自学了一点VC++,大三的时候也试着编写过一个MFC的最简单的窗口程序。到大四的时候,自己又做了一个GIS的项目,是用C#.NET来编写的,然后发现C#上手好容易,而且还大部分语法规则都沿用了C,C++的习惯,于是觉得C++实在是没有一点优势可言啊。但这个暑假的实习经历又改变了我的观点:C++在写窗口程序虽然麻烦,但是却什么能做,而且对比C#来说,对运行环境的要求不高,不用像C#程序在安装之前还要安装100M多的运行.NET环境。C++和C#各有优缺,目前我对它们俩的定位是:C++用来写一些底层的程序,比如驱动,或者是一些算法类型的函数接口,然后用C#来调用这些接口并进行界面设计。如何函数的实现跨语言呢?显然DLL是个很重要的内容,故在此对VC++的DLL模块进行介绍。

1 用VC创建DLL动态连接库

1.1 创建dll项目

然后选择“一个空的dll工程”,然后点击“确定”便完成了“创建dll项目”的流程。

1.2 为dll项目编写源文件

新建两个文件:dllDemo.h, dllDemo.cpp

在头文件”dllDemo.h”中声明三个接口函数:

extern "C" _declspec(dllexport) int Sum(int a,int b);//加法函数。

extern "C" _declspec(dllexport) int Max(int a, int b);//取较大值函数

extern "C" _declspec(dllexport) int Min(int a, int b);//取较小值函数

然后在“dllDemo.cpp”文件中实现三个接口函数:

#include "dllDemo.h"

extern "C" _declspec(dllexport)int Sum(int a, int b)

{

return a+b;

}

extern "C" _declspec(dllexport)int Max(int a, int b)

{

if(a>=b)return a;

else

return b;

}

extern "C" _declspec(dllexport)int Min(int a, int b)

{

if(a>=b)return b;

else

return a;

}

1.3 生成dll文件

编译源文件,如果没有出现错误提示,那么,在项目文件根目录的Debug文件夹内会生成一个dll文件“dllDemo.dll”。

2 DLL调用

2.1 用C++调用显式链接

新建一个Win32的控制台程序进行显式调用:

1. 新建“dllConsoleEvident”的Win32控制台程序项目

2. 新建cpp文件“dllConsoleEvident.cpp”

3. 将在第一节中,在Debug目录下编译生成的“dllDemo.dll”(显式调用时只需要这一个文件就够了)文件复制到“dllConsoleEvident”项目下的Debug文件夹根目录下

4. 在“dllConsoleEvident.cpp”文件中编写以下代码对dll中的函数进行显式调用

代码

//////////////////////////////////////////////////////////////////////////

//动态加载DLL文件

#include 

#include

void main(void)

{

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<<"比较的结果为"<}

if (Min)

{

int B=Min(5,8);

cout<<"比较的结果为"<}

FreeLibrary(hDLL);//卸载MyDll.dll文件;

}

2.2 用C++隐式链接(Win32控制台程序)

新建一个Win32控制台程序演示静态调用

1. 利用向导新建“dllConsoleStaticDemo”的空工程

2. 将“dllDemo.dll”和“dllDemo.lib”文件复制到Debug目录下,并在项目中包含“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);

#include 

void main()

{

int c=Sum(4,5);

c=Max(5,6);

c=Min(5,6);

cout<<"Hello,dllConsoleTest~!";

}

4.通过断点,可以看到dll函数调用成功

这种方式的静态调用的特点是:在程序一开始执行的时候,就将dll文件全部加载到程序中,不会释放。

2.3 用C++隐式链接(MFC窗口程序)

新建一个MFC基本对话框窗口程序进行调用:

1. 利用向导建立一个MFC基本对话框

2. 将“dllDemo.dll”和”dllDemo.lib”文件复制到本项目的Debug目录下,在VC工作空间的文件视图下面将”dllDemo.lib”添加到项目中

3. 在“dllMfcDemoDlg.h”头文件中的前面对来自外部的dll函数进行声明

// dllMfcDemoDlg.h : header file

//

#if !defined(AFX_DLLMFCDEMODLG_H__E358B876_D188_48FD_8D83_794309C885A9__INCLUDED_)

#define AFX_DLLMFCDEMODLG_H__E358B876_D188_48FD_8D83_794309C885A9__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////

// CDllMfcDemoDlg dialog

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: Add extra validation here

  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”文件复制到项目的Debug目录下面

3. 在“Program.cs”中编写如下代码

代码

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;//引入dll文件中的函数

namespace ConsoleDllDemo

{

class Program

{

//引入dll文件中的函数

[DllImport("dllDemo.dll")]

private static 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);

static void Main(string[] args)

{

int a = Sum(3, 5);

Console.WriteLine(a);

Console.WriteLine(Max(5,10));

Console.WriteLine(Min(12,25));

Console.ReadKey();//要按键才退出。

}

}

}

然后断点单步运行,便可以看到调用函数的结果了。

关于DLL的调用的更详细内容可以参考另外一些文章:

http://dev.firnow.com/course/3_program/c++/cppsl/2008127/97781.html

http://dev.yesky.com/283/20283_2.shtml

3 dll调试方法

在建立了dll项目后,并写好相应的实现代码,点击“运行”,会弹出现在的对话框:

然后浏览,找到一个调用了此dll文件的执行文件“*.exe”文件,然后就可以对dll文件进行断点调试了。

这个“*.exe”文件可以是任何平台的,C++也可以,C也可以,C#也可以,只要这个执行文件调用了dll文件中的函数即可。

如果想更换调试的“*.exe”文件,可以在“工程-》设置”对话框中的“调试”选项卡进行设置,浏览找到用户需要的“*.exe”文件

说明:以VC++环境中调用此dll为例,运行dllDemo项目,然后会调用“*.exe”文件,如果此exe文件含有源文件,而且刚好在源文件的Debug目录下面,那么,可以同时在exe文件的源文件中设置断点,进行dll和调用dll两个程序的联调。(好像跨语言调用的时候不能进行联调,笔者只在C++互相调用的时候联调成功过,但C#调用的时候没有联调成功,这个问题有待解决)

4. DLL返回数据类型探究

目前写的DLL函数反返回值还仅限于整形,还没有尝试其它特殊类型的返回值。更丰富的返回值类型,还要今后慢慢学习和研究。等回学校了再研究吧。请见后续文章吧。

附件:

VC_dll_Realse.rar中是VC编写DLL并引用DLL的相关源码文件

CShapr_ConsoleDllDemo.rar中是VS2005编写的C#引用VC编写的DLL函数的相关源码文件

http://files.cnblogs.com/beer/VC_dll_Realese.rar

http://files.cnblogs.com/beer/CSharp_ConsoleDllDemo.rar

下载本文
显示全文
专题