轉載自:
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 onceclass 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