当前位置 : 主页 > 编程语言 > c语言 >

C++制作DLL文件的方法详解

来源:互联网 收集:自由互联 发布时间:2023-05-16
目录 一、DLL介绍 二、C++制作DLL文件 2.1 DLL端 2.2 调用端 三、DLL导出类方法 一、DLL介绍 我理解的DLL是windows下的可执行文件,也就是PE文件,学名动态链接库。一般调用DLL,也称加载DLL的
目录
  • 一、DLL介绍
  • 二、C++制作DLL文件
    • 2.1 DLL端
    • 2.2 调用端
  • 三、DLL导出类方法

    一、DLL介绍

    我理解的DLL是windows下的可执行文件,也就是PE文件,学名动态链接库。一般调用DLL,也称加载DLL的是EXE文件。它是一种可重用的代码和数据的集合,可以由多个应用程序同时使用,与静态链接库不同,动态链接库在运行时加载到内存中,以供应用程序使用。

    一个exe程序可以带若干个dll,如下图:

    正常的windows程序基本都会带DLL,包括操作系统内核的DLL,所以很关键。

    DLL具有以下优点:

    • 可重用性:由于多个应用程序可以共享一个DLL,因此它们可以共享相同的代码和数据,从而提高了代码的可重用性。
    • 节省内存:由于DLL在运行时才加载到内存中,因此它们可以在不占用过多内存的情况下提供所需的功能。
    • 易于更新:当需要更新DLL时,只需替换现有的DLL文件即可,而无需重新编译使用该DLL的应用程序。
    • 动态链接:DLL在运行时才链接到应用程序中,因此它们可以在应用程序启动后动态加载,从而提高了应用程序的启动速度。
    • 稳定性:由于多个应用程序共享相同的DLL,因此如果DLL中的代码或数据发生问题,则可以在一次更新后修复所有使用该DLL的应用程序。

    使用DLL的过程分为两个步骤:首先需要创建一个DLL,然后在需要使用该DLL的应用程序中加载它。为了使DLL中的函数可以在应用程序中使用,必须将其导出,可以使用__declspec(dllexport)修饰符来导出DLL中的函数和数据。而在应用程序中调用DLL中的函数,需要使用LoadLibrary()函数来加载DLL,并使用GetProcAddress()函数获取DLL中导出函数的地址,然后使用函数指针来调用这些函数。

    在Linux下,与之对应的是.so文件。MacOs下为.dylib。

    二、C++制作DLL文件

    需要打开你的windows Visual Satdio任意版本。可以直接选择创建DLL文件,也可以先创建平台程序后续再改。

    这里直接展示一段简单的代码。

    2.1 DLL端

    DllDLL.h:

    #pragma once
    #ifdef MYLIBRARY_EXPORTS
    #define MYLIBRARY_API __declspec(dllexport)
    #else
    #define MYLIBRARY_API __declspec(dllimport)
    #endif
     
    MYLIBRARY_API int Add(int a, int b);

    DllDLL.cpp:

    #include "DllDLL.h"
     
    int Add(int a, int b)
    {
    	return a + b;
    }

    DllDLL.def模块定义:

    LIBRARY GeneratrDLL
    EXPORTS
    Add @1

    模块定义需要在这设定:

    重点:

    .def文件(也称为导出文件)是一种Windows平台上的文件格式,用于描述可执行文件或动态链接库(DLL)中导出函数的名称和地址。当编写一个DLL并将其与其他应用程序链接时,该DLL中的函数必须明确导出,以便其他应用程序能够调用这些函数。

    2.2 调用端

    代码:

    #include "..\DllDLL\DllDLL.h"
    #include <windows.h>
    #include <iostream>
    typedef int(*AddFunc)(int, int);
     
    int main()
    {
    	HINSTANCE hinstLib = LoadLibrary(TEXT("DllDLL.dll"));
    	if (hinstLib != NULL)
    	{
    		AddFunc add = (AddFunc)GetProcAddress(hinstLib, "Add");
    		if (add != NULL)
    		{
    			// 调用 DLL 中的函数
    			int result = add(1, 2);
    			std::cout << result << std::endl;
    		}
    	}
     
    }

    将UseDllDLL设置为启动项,运行结果(DLL内部返回方法的结果):

    三、DLL导出类方法

    我们定义一个MyInterface基类,里面实现虚方法,再生成一个它的派生类实现虚方法,最后创建类工厂让客户端代码更容易实例化类对象。

    // MyInterface.h
    #ifndef MY_INTERFACE_H
    #define MY_INTERFACE_H
     
    class MyInterface
    {
    public:
    	virtual ~MyInterface(){}
    	virtual void DoSomething() = 0;
    	virtual int GetNumber() = 0;
    };
     
    class MyImplementation : public MyInterface
    {
    public:
    	virtual void DoSomething() override;
    	virtual int GetNumber() override;
    };
    #endif // MY_INTERFACE_H
     
     
     
     
    // MyImplementation.cpp
    #include "MyInterface.h"
     
    void MyImplementation::DoSomething()
    {
    	//
    }
     
    int MyImplementation::GetNumber()
    {
    	return 49;
    }
     
     
     
    // MyDLL.h
    #ifndef MY_DLL_H
    #define MY_DLL_H
     
    #ifdef MY_DLL_EXPORTS
    #define MY_DLL_API __declspec(dllexport)
    #else
    #define MY_DLL_API __declspec(dllimport)
    #endif
     
    #include "MyInterface.h"
     
    MY_DLL_API MyInterface* CreateMyObject();
     
    #endif // MY_DLL_H
     
     
     
    // MyDLL.cpp
    #define MY_DLL_EXPORTS
    #include "MyDLL.h"
    #include "MyInterface.h"
     
     
    MyInterface* CreateMyObject()
    {
    	return new MyImplementation();
    }

    上面代码的最后两端将MyInterface* 类的对象作为导出接口,它的我实现是返回它的派生类MyImplementation类的实例对象。客户端可以使用CreateMyObject获得实例。

    客户端调用DLL,首先要有实现DLL的头文件MyInerface.h,然后去调用,具体:

    #include "..\GeneratrDLL\MyInterface.h"
    #include <Windows.h>
    #include <iostream>
     
    int main()
    {
    	// 加载DLL
    	HMODULE hModule = LoadLibrary(L"C:\\Users\\liubw\\source\\repos\\GeneratrDLL\\x64\\Debug\\GeneratrDLL.dll");
     
    	if (hModule != NULL)
    	{
    		// 获取接口
            typedef MyInterface* (*CreateMyObjectFunc)();
    		CreateMyObjectFunc fun = (CreateMyObjectFunc)GetProcAddress(hModule, "CreateMyObject");
     
    		if (fun != NULL)
    		{
    			// 使用接口
    			MyInterface* myObject = createMyObject();
    			myObject->DoSomething();
    			int number = myObject->GetNumber();
    			std::cout << number << std::endl;
    			delete myObject;
    		}
    		else
    		{
    			// 无法获取接口
    		}
     
    		// 卸载DLL
    		FreeLibrary(hModule);
    	}
    	else
    	{
    		// 无法加载DLL
    	}
     
    	return 0;
    }

    其中typedef MyInterface* (*CreateMyObjectFunc)();声明了MyInterface*函数指针的函数CreateMyObjectFunc,并且没有参数,我们可以用CreateMyObjectFunc代替返回值为MyInterface*的函数的声明。具体如下:

    【C/C++】中【typedef】用法大全

    以上就是C++制作DLL文件的方法详解的详细内容,更多关于C++制作DLL文件的资料请关注自由互联其它相关文章!

    上一篇:C++如何采用Daemon进行后台程序的部署
    下一篇:没有了
    网友评论