`

C++下的DLL编程入门

 
阅读更多

 

 

一、 编写第一个入门级dll文件

 

1. 新建一个dlltest的dll工程,加入一源文件dlltest.cpp,包含add和subtract两个函数如下:

 

_declspec(dllexport) int add(int a,int b)
{
    return a+b;
}

_declspec(dllexport) int subtract(int a,int b)
{
    return a-b;
}

 

 

注意:

在函数名前加上_declspec(dllexport)这样编译后在连接的时候才会生成dlltest.lib(引入库文件)和dlltest.exp(输出库文件),并且在命令提示符下用dumpbin命令可以看到导出了哪些函数。

方法:在命令提示符下,转到dll文件所在目录下,输入dumpbin –exports dlltest.dll,列出导出函数如下:

 

这里注意到函数名字已经被改成了?add@@YAHHH@Z,这种现象叫做名字粉碎,是为了支持函数重载而做的。

 

2.编写一个基于对话框的MFC程序测试DLL,工程名为calldll,放置两个按纽add和subtract,响应按纽消息,调用这个DLL的add和subtract函数。

先添加响应按钮消息的函数OnAdd和OnSubtract,然后在函数所在源文件中写完整函数体如下:

 

//extern int add(int,int);
//extern int subtract(int,int);
_declspec(dllimport) int add(int,int);
_declspec(dllimport) int subtract(int,int);

void CCalldllDlg::OnAdd() 
{
    // TODO: Add your control notification handler code here
    CString str;
    str.Format("2+3=%d",add(2,3));
    MessageBox(str);
}

void CCalldllDlg::OnSubtract() 
{
    // TODO: Add your control notification handler code here
    CString str;
    str.Format("3-2=%d",subtract(3,2));
    MessageBox(str);
}



 

 

这里采用隐式链接的方式加载动态链接库:

注意:要用关键字extern先声明这两个函数,表明这两个函数是在外部定义的(不过程序中将它注释掉了)。最好是用_declspec(dllimport)表明函数是从动态链接库的lib文件中引入的,这样效率更高。

 

将文件dlltest.lib拷贝到此工程目录下,并在Project Settings的Link标签下添加此文件:(否则编译会成功,但连接时会出错提示找不到函数的定义)

 

编译连接生成calldll.exe,这时用Dumpbin -importscalldll.exe查看它的输入信息,可以看到它加载了dlltest.dll

 

运行calldll.exe(要成功运行还需将dlltest.dll拷贝到工程目录或此exe所在目录下)

 

这样,最简单的第一个dll就完成了。

 

 

二、 编写涉及到类和头文件的dll文件

 

1. 新建一个dlltest的dll工程,加入一头文件dlltest.h和一源文件dlltest.cpp。

dlltest.h:

 

#ifdef DLL_API
#else
#define DLL_API _declspec(dllimport)
#endif

DLL_API int add(int,int);
DLL_API int subtract(int,int);

class DLL_API Point1               //将整个类导出
{
public:
    void output(int x,int y);
    void output1(int x,int y);
};

class Point2
{
public:
    DLL_API void output(int x,int y);   //仅导出类中的一个函数
    void output1(int x,int y);
};



 

dlltest.cpp

 

#define DLL_API _declspec(dllexport)
#include "dlltest.h"
#include <windows.h>
#include <stdio.h>

int add(int a,int b)
{
    return a+b;
}

int subtract(int a,int b)
{
    return a-b;
}

void Point1::output(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,"x=%d,y=%d",x,y);
    TextOut(hdc,0,0,buf,strlen(buf));
}

void Point1::output1(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,"x=%d,y=%d",x,y);
    TextOut(hdc,0,0,buf,strlen(buf));
}

void Point2::output(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,"x=%d,y=%d",x,y);
    TextOut(hdc,0,20,buf,strlen(buf));
}

void Point2::output1(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,"x=%d,y=%d",x,y);
    TextOut(hdc,0,20,buf,strlen(buf));
}



 

2. 编写一个基于对话框的MFC程序测试DLL,此时在工程中包含上面这个头文件,不用在声明导入的类和函数了。

三、 使用模块定义文件和动态加载动态链接库

1. 新建dlltest.dll工程,加入一源文件dlltest.cpp,包含add和subtract两个函数如下:

 

int add(int a,int b)
{
    return a+b;
}

int subtract(int a,int b)
{
    return a-b;
}

 

 

2. 使用模块定义文件防止文件名改变,在目录中新建dlltest.def文件,增加到工程。

LIBRARY dlltest
EXPORTS
add
subtract

 

注:LIBRARYEXPORTS的用法参照MSDN.

3. 编译后用dumpbin查看到函数名没有改变。

 

4. 用动态加载的方法来调用dll文件。

 

void CCalldllDlg::OnAdd() 
{
       // TODO: Add your control notification handler code here
       HINSTANCE hInst;
       hInst=LoadLibrary("dlltest.dll");
       typedef int (/*_stdcall*/ *ADDPROC)(int a,int b);
       //ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"?add@@YAHHH@Z");
       //ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));
       ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");
       if(!Add)
       {
              MessageBox("获取函数地址失败!");
              return;
       }
       CString str;
       str.Format("2+3=%d",Add(2,3));
       MessageBox(str);
       FreeLibrary(hInst);
}

 

 

注意:

1. 这里调用的GetProcAddress函数中的第二个参数是动态链接库中导出的函数名,如果动态链接库中没有用模块定义文件防止函数名粉碎,则要用注释掉的GetProcAddress(hInst,"?add@@YAHHH@Z"),另外也可按序号访问GetProcAddress(hInst,MAKEINTRESOURCE(1))

2. 使用模块定义文件后,如果改变调用约定为_stdcall,函数名也不会被改变,但如果加上_stdcall定义函数,调用时也需要加上_stdcall,否则会出错。

3. 动态加载不需要将文件dlltest.lib拷贝到此工程目录下,并在Project Settings的Link标签下添加此文件,只需将dll文件拷贝到工程目录下即可,并且通过dumpbin -imports calldll.exe查看它的输入信息时,可以看到它并没有加载dlltest.dll。

4. 动态加载的好处是需要时再加载,可以提高执行的效率。当不使用DLL时,调用FreeLibrary减少DLL的使用计数,释放DLL资源,减少系统负担。

5. 不使用模块定义文件,也可用extern "C"使函数名保持不变,如#define DLL1_API extern "C" _declspec(dllexport),但它只能导出全局函数,不能导出类的成员函数,并且如果调用约定被改成了别的方式,此时函数名也被改变,所以一般不用这种方式。

 

分享到:
评论

相关推荐

    用C++进行DLL编程入门

    C++进行DLL编程入门 一、C++中的DLL编程入门 在C++中,DLL(Dynamic Link Library)是一种非常重要的编程技术,允许开发者将代码封装到一个库文件中,然后在其他应用程序中使用。下面将详细介绍如何使用C++进行DLL...

    C++实现的DLL编程入门

    C++实现的DLL编程入门是计算机编程领域中的一个重要概念,主要应用于Windows平台的软件开发。DLL(Dynamic Link Library)是一种可执行文件格式,允许多个应用程序共享同一块代码和数据,从而节省内存并提高效率。本...

    C++dll编程入门[整理].pdf

    本文主要介绍C++中DLL编程的基础知识,包括静态链接库和动态链接库的区别,以及如何创建和调用DLL。 首先,我们来看静态链接库和动态链接库的异同点。静态链接库(.lib)在编译时会被合并到可执行文件(.exe)中,...

    C++dll编程入门.pdf

    C++dll编程入门.pdf

    C++ Dll 编写入门

    【C++ DLL 编写入门】 DLL(Dynamic Link Library)是Windows操作系统中广泛使用的一种库文件格式,它允许多个应用程序共享代码和资源,从而优化内存使用和提高软件开发效率。DLL文件包含了函数、类和资源,可以被...

    dll编程入门(C++语言).pdf

    C++下的DLL编程是开发软件时常用的一种技术,它可以实现代码的复用和模块化。以下是对DLL编程的详细介绍: 1. **创建DLL文件** - 在C++中,我们可以通过Visual Studio创建一个新的DLL工程,比如`dlltest`。在这个...

    C++Dll编写入门

    ### C++ DLL编写入门 #### 一、DLL在Windows操作系统中的重要性 动态链接库(Dynamic Link Library,简称DLL)自微软推出16位的Windows操作系统以来,便成为了Windows架构的核心组成部分。每一个版本的Windows,从...

    VC++DLL编程入门

    ### VC++ DLL编程入门知识点详解 #### 一、概述 **动态链接库(Dynamic Linkable Library,DLL)** 是一种可被多个程序同时使用的代码和数据集合,它为应用程序提供了可重用的功能。通过使用DLL,可以实现代码的...

    Visual C++ ADO 数据库编程入门

    ### Visual C++ ADO 数据库编程入门 #### 一、ADO技术概述 ##### 1.1 ADO技术简介 ADO (ActiveX Data Objects) 是一种高级数据库编程接口,它基于OLE DB技术之上,专为Windows环境设计。ADO以其强大的数据处理能力...

    非MFC简单DLL编程,C++

    ### 非MFC简单DLL编程,C++ #### 概述 动态链接库(Dynamic Link Library,简称DLL)是Windows操作系统中的一个重要组成部分,用于存放可由多个程序同时使用的代码和数据。通过使用DLL,可以有效地减少内存占用量...

    C++多线程编程入门小结.pdf

    根据给定文件信息,以下是对"C++多线程编程入门小结.pdf"文件内容的知识点说明: ### 知识点一:C++多线程编程基础 C++多线程编程是指在C++程序中同时执行多个线程,以利用现代处理器的多核能力,提高程序的执行...

    dll编程入门

    dll编程入门(C++)语言,介绍如何在C++环境下编写dll文件,开启动态链接库DLL之旅。

    在Borland C++ Builder6中写DLL初步入门.doc

    在Borland C++ Builder6中创建和使用DLL(动态链接库)是一个常见的编程任务,这对于软件开发中的模块化和代码重用至关重要。本教程主要介绍了如何通过简单的步骤实现DLL的编写和调用。 首先,我们需要创建一个DLL...

    DLL动态链接库编程入门(5文件)

    4. **非MFC DLL编程**:文件可能介绍如何在不使用MFC的情况下编写和使用DLL,可能包括线程安全、内存管理和资源管理等主题。 5. **DLL问题和解决策略**:可能讨论常见的DLL问题,如版本冲突、命名冲突和依赖性问题,...

    dll编程入门(C++语言).docx

    。。。

    基于Visual C++6.0的DLL编程实现

    ### 基于Visual C++6.0的DLL编程实现 #### 一、DLL简介与重要性 动态链接库(Dynamic Link Library,简称DLL)是Windows操作系统中的一个重要组成部分,广泛应用于各种应用程序中。通过DLL,可以实现代码和数据的...

Global site tag (gtag.js) - Google Analytics