转载自:
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