当前位置: 首页 > 编程笔记 >

C++编写DLL动态链接库的步骤与实现方法

利博远
2023-03-14
本文向大家介绍C++编写DLL动态链接库的步骤与实现方法,包括了C++编写DLL动态链接库的步骤与实现方法的使用技巧和注意事项,需要的朋友参考一下

本文实例讲述了C++编写DLL动态链接库的步骤与实现方法。分享给大家供大家参考,具体如下:

在写C++程序时,时常需要将一个class写成DLL,供客户端程序调用。这样的DLL可以导出整个class,也可以导出这个class的某个方法。

一、导出整个class

方法很简单,只需要在类的头文件中class和类名之间加上_declspec(dllexport),同时在另外一份提供给客户端调用程序使用的类的头文件中class和类名之间加上_declspec(dllimport)。为了能让客户端程序和DLL程序公用该类的一份头文件,通常在类的头文件中使用宏和预编译指令来处理。如下DLLTest.h:

#ifdef DLL_TEST_API
#else
#define DLL_TEST_API _declspec(dllimport)
#endif
Class DLL_TEST_API CDLLTest
{
   Public:
     CDLLTest();
     ~CDLLTest();
     int Add(int a, int b);
};

DLLTest.cpp如下:

#define DLL_TEST_API  _declspec(dllexport)
#include "DLLTest.h"

这样,在DLL编译时DLL_TEST_API被定义为_declspec(dllexport),而且客户端程序编译时它被定义为_declspec(dllimport)。

二、导出这个类的某个或者某几个方法

这时,需要将_declspec(dllexport)放到成员函数名前,如DLLTest.h:

#ifdef DLL_TEST_API
#else
#define DLL_TEST_API _declspec(dllimport)
#endif
Class CDLLTest
{
   Public:
      CDLLTest();
         ~CDLLTest();
      int DLL_TEST_API Add(int a, int b);
};

但是,如果仅仅是这样的话,当客户端程序#include这个头文件后,定义DLLTest这个类的一个对象后(静态方式链接DLL),客户端程序无法链接通过,会提示构造函数和析构函数无法解析,此时,需要将构造函数和析构函数前也加上DLL_TEST_API宏即可。

当然这里还有个问题就是类的函数在导出后,名字会发生变化,我们可以在函数名前再加上extern "C" ,如 extern "C" DLL_TEST_API int Add(int a ,int b);但这只解决了C与C++调用时名字变更问题,可靠的方法还是增加一个模块定义文件def,在该文件中定义导出函数的名称,我们将在后面看到样例。

DLL编写完成后,就只剩下客户端程序如何去调用该DLL了,静态方式调用DLL和动态方式调用DLL。

一、静态方式调用DLL

这个方法就简单了,将DLLTest.h头文件和DLLTest.lib,DLLTest.dll文件拷贝到客户端程序的当前目录下,在客户端程序中#include<DLLTest.h>,然后通过#pragma comment(lib,"DLLTest.lib")的方式引入lib库,或者在客户端程序的工程属性里面增加对该lib文件的引入。

然后就可以在客户端程序中如同使用本地的一个class一样使用该DLL了,如:

CDLLTest dllTest;
dllTest.Add(1,2);

二、动态方式调用DLL

动态调用这个DLL,就需要对这个class进行修改了。

首先,在DLLTest.cpp文件中增加一个全局函数,该函数可以返回这个class的一个实例,这样,客户端程序调用这个全局函数后,得到该class的实例,就可以调用该class的实例方法了。

extern "C" _declspec(dllexport) CDLLTest* GetInstance()
{
   return new CDLLTest;
}

注:extern "C" 只是解决了c与c++编译器之间的兼容问题,如果需要和其他编译器之间兼容,可靠的办法还是增加一个.def文件,文件内容如下:

LIBRARY "DLLTest"
EXPORTS
GetInstance = GetInstance

这样就指定了DLL的函数导出后的名称仍然不变。

这样,客户端程序就可以通过该函数来获取class的一个实例了。如下:

先需要定义一个函数指针类型:

typedef CDllTestBase* (*pfGetInst)();
//注:CDllTestBase类后面会介绍。
HMOUDLE hMod = LoadLibrary( _T("DLLTest.DLL") );
if(hMod)
{
  pfGetInst pfGetInstance = (pfGetInst)GetProcAddress("GetInstance");
  if( p )
  {
   //通过基类指针指向派生类对象
    CDllTestBase * pInst = pfGetInstance ();
   if( NULL != pInst )
   {
    pInst->Add( 1,2);
   }
      if( NULL != pInst )
   {
    //释放对象
    delete pInst;
   }
  }
}

当然,这里还是需要include这个DLL的头文件DLLTestBase.h,如果将之前所写的头文件DLLTest.h直接拷贝到客户端程序的当前目录下,并include进来的话,在编译连接时,是无法通过的,我们需要对这个头文件进行修改,首先增加一个.h 文件DLLTestBase.h,在这个文件中我们将需要在客户端程序中调用的函数都命名成纯虚函数,然后让CDLLTest类继承自CDLLTestBase类,DLLTestBase.h如下:

Class CDLLTestBase
{
  Public:
    Virtual ~CDLLTestBase(){};//虚析构函数,且为内联函数
     Virtual int Add(int a, int b) = 0;
}

DLLTest.h修改后如下:

#include "DLLTestBase.h"
Class CDLLTest : public CDLLTestBase
{
  Public:
    CDLLTest();
    ~CDLLTest();
    int Add(int a, int b);
};

注:这里的DLLTestBase需要提供一个虚析构函数,这样在客户端程序中就可以通过基类指针来释放派生类对象了。

这样,只需要将DLLTestBase.h拷贝到客户端程序的当前目录下,然后在客户端程序中#include"DLLTestBase.h",就可以如上面介绍一样在客户端程序中调用DLL里面的方法了。

希望本文所述对大家VC++程序设计有所帮助。

 类似资料:
  • 本文向大家介绍C#实现动态加载dll的方法,包括了C#实现动态加载dll的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#实现动态加载dll的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的C#程序设计有所帮助。

  • 本文向大家介绍使用python创建生成动态链接库dll的方法,包括了使用python创建生成动态链接库dll的方法的使用技巧和注意事项,需要的朋友参考一下 如今,随着深度学习的发展,python已经成为了深度学习研究中第一语言。绝大部分的深度学习工具包都有python的版本,很多重要算法都有python版本的实现。为了将这些算法应用到具体工程中,这些工具包也提供了不同类型的接口。 动态链接库(.d

  • 本文向大家介绍C++调用C#的DLL实现方法,包括了C++调用C#的DLL实现方法的使用技巧和注意事项,需要的朋友参考一下 SwfDotNet是C#编写的,这是个特别好的读写Swf文件的库。本文讲述了在C++项目中,怎么让C++调用C#的DLL动态链接库文件。 具体的实现步骤如下: 一、创建C# DLL,需要指定应用类型为“类库”,代码: 二、C++客户程序,是个控制台应用,代码: 三、这里有几点

  • 动态链接库(也称为DLL)是Microsoft Windows最重要的组成要素之一。大多数与Windows相关的磁盘文件如果不是程序模块,就是动态链接程序。迄今为止,我们都是在开发Windows应用程序;现在是尝试编写动态链接库的时候了。许多您已经学会的编写应用程序的规则同样适用于编写这些动态链接库模块,但也有一些重要的不同。 动态链接库的基本知识 正如前面所看到的,Windows应用程序是一个可

  • 本文向大家介绍C#实现异步编程的方法,包括了C#实现异步编程的方法的使用技巧和注意事项,需要的朋友参考一下 最近在我参与的几个.Net项目中都有用到异步编程,作为一名.Net小白,很有必要好好地学习一下C#异步编程。 什么是异步 异步指的就是不用阻塞当前线程来等待任务的完成,而是将任务扔到线程池中去执行,当前线程可以继续向下执行,直至其它线程将任务完成,并回调通知当前线程。整个任务从开始到结束都是

  • 本文向大家介绍VC程序在Win32环境下动态链接库(DLL)编程原理,包括了VC程序在Win32环境下动态链接库(DLL)编程原理的使用技巧和注意事项,需要的朋友参考一下 本文详细讲述了VC程序在Win32环境下动态链接库(DLL)编程原理。分享给大家供大家参考。具体分析如下: 一般比较大的应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作。其中可能存在

  • 问题内容: 我试图将静态库(与gcc一起编译)链接到C 程序,但出现了“未定义引用”。我在ubuntu 12.04服务器计算机上使用了gcc和g 版本4.6.3。例如,这是阶乘方法的简单库文件: mylib.h mylib.c 我使用gcc为此mylib.c创建了对象: 再次使用AR实用工具从目标文件创建了静态库: 我用C程序(test.c)和C ++程序(test.cpp)测试了这个库 C和C

  • 主要内容:静态链接库,动态链接库,总结我们知道,C、C++程序从源文件到生成可执行文件需经历 4 个阶段,分别为预处理、编译、汇编和链接,本节将重点围绕链接阶段,对静态链接库和动态链接库做详细的讲解。 有关链接操作的具体细节,感兴趣的读者可阅读《 到底什么是链接,它起到了什么作用?》和《 符号——链接的粘合剂》这两节。总的来说链接阶段要完成的工作,就是将同一项目中各源文件生成的目标文件以及程序中用到的库文件整合为一个可执行文件。 通过