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