c++显式加载dll并使用DLL的类

时间:2022-07-18 09:39:42
转载自:


http://blog.163.com/tianjunqiang666@126/blog/static/8725911920121064573594/

首先需要强调,当使用某个类时一般目的有二:实例化成对象或者继承它产生新类。
对于前者,我们可以构造一个抽象类(java里的接口)来连接调用方和DLL。
// Interface.h  公共文件///////////////////////////////////////////////// 公共接口

// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 INTERFACE_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// INTERFACE_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef INTERFACE_EXPORTS
#define INTERFACE_API __declspec(dllexport)
#else
#define INTERFACE_API __declspec(dllimport)
#endif

#pragma once

class Interface
{
public:
	virtual void ShowMsg() = 0; // 将调用方需要调用的成员函数声明成纯虚函数
	virtual ~Interface(){};// 抽象类的虚析构函数
};
extern "C" INTERFACE_API Interface* Export(void);
// Interface.cpp  被调用方文件////////////////////////////////////////////////


//  注意下面的代码并不是实现 Interface 类,而是因为联系紧密才写在这。

// Interface.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "Interface.h"
#include <iostream>
#include "test.h"


// 通过导出函数形式向调用方提供指向派生类对象的基类指针
Interface* Export(void)
{
	return (Interface*)new Test();
}
将真正要调用的类声明成抽象类 Interface 的派生类:

#pragma once
#include "Interface.h"
#include <string>
class Test :public Interface
{
public:
	Test();
	virtual ~Test();
	virtual void ShowMsg(void);
private:
	std::string s;
};

// Test.cpp  被调用方文件////////////////////////////////////////


//  类的实现
#include "stdafx.h"
#include "test.h"
#include <iostream>

Test::Test()
{
	s = "hello form dll";
}

Test::~Test()
{
	std::cout << "destroy";
}

void Test::ShowMsg()
{
	std::cout << s << std::endl;
}


调用方调用DLL时动态加载:

#include <Windows.h>
#include <iostream>
#include "Interface.h" // 包含抽象类从而使用接口

// 在调用处添加如下代码
using pExport = Interface* (*)(void); // 定义指向导出函数的指针类型

int main()
{
	HINSTANCE hDll = LoadLibrary("Interface.dll");// 加载DLL库文件,DLL名称和路径用自己的
	if (hDll == NULL)
	{
		std::cout << "load dll fail \n";
		return -1;
	}
	pExport Get = (pExport)GetProcAddress(hDll, "Export");// 将指针指向函数首地址
	if (Get == NULL)
	{
		std::cout << "load address fail \n";
		return -1;
	}

	Interface *t = Get();// 调用导出函数获得抽象类指针
	t->ShowMsg();// 通过该指针调用类成员函数
	delete t; // 释放DLL中生成的对象
	FreeLibrary(hDll); //释放库句柄
	system("pause");
	return 0;
}


此时需要注意两点:

1.我们需要把Interface.h放在UseDLL工程目录下

2.如果编译时出现:无法将参数 1 从“const char [14]”转换为“LPCWSTR”的错误,则我们需要

点击项目属性,常规-》字符集-》改为“未设置”即可

实际上整个项目的方法是Interface完成了接口的设置,而具体的实现在test中进行,真正使用了类的抽象性和多态性,封闭性。

项目下载路径:http://7xs15g.com1.z0.glb.clouddn.com/Interface.zip