前言
假设第三方DLL中的导出类有我们关系的功能
我们没有整理出完整的.h, 只有几个关心的导出类接口定义, 这最符合实际情况.
我们需要手工调用导出类的接口
调用方代码
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
/// CTestOnDll是第三方的Dll, 假设接口很多, 我们没有时间整理出全部的准确接口定义
/// 只想使用其中的几个关心的接口
// #include "MyDll.h" ///< 没有完整的.h来包含
class CTestOnDllEx; ///< 一个不存在的类, 没有头文件支持
CTestOnDllEx* g_pClass = NULL;
union unionFunConvert {
FARPROC pfnFarProc;
void (CTestOnDllEx::*PFN_CTestOnDllEx)(); ///< 构造函数
void (CTestOnDllEx::*PFN__CTestOnDllEx)(); ///< 析构函数
int (CTestOnDllEx::*PFN_CTestOnDll_Add)(int iLeft, int iRight); ///< 导出类接口-加法
int (CTestOnDllEx::*PFN_CTestOnDll_Sub)(int iLeft, int iRight); ///< 导出类接口-减法
};
void fnCall3rdExportClass(); ///< 调用我们自己的导出类Dll的方法
int main(int argc, char* argv[])
{
printf("dynamic call 3rd export class on dll!\n");
fnCall3rdExportClass();
/** run result
dynamic call 3rd export class on dll!
CTestOnDll::CTestOnDll()
(pClass->*(convert.PFN_CTestOnDll_Add))(1, 2) = 3
(pClass->*(convert.PFN_CTestOnDll_Sub))(1, 2) = -1
CTestOnDll::~CTestOnDll()
*/
return 0;
}
/**
>> ??0CTestOnDll@@QAE@ABV0@@Z == CTestOnDll::CTestOnDll
>> ??0CTestOnDll@@QAE@XZ == CTestOnDll::CTestOnDll
>> ??1CTestOnDll@@UAE@XZ == CTestOnDll::~CTestOnDll
>> ??4CTestOnDll@@QAEAAV0@ABV0@@Z == CTestOnDll::operator=
>> ??_7CTestOnDll@@6B@ == CTestOnDll::`vftable'
>> ?Add@CTestOnDll@@UAEHHH@Z == CTestOnDll::Add
>> ?Sub@CTestOnDll@@QAEHHH@Z == CTestOnDll::Sub
*/
void fnCall3rdExportClass() {
CTestOnDllEx* pClass = NULL;
HINSTANCE hDll = NULL;
unionFunConvert convert;
ZeroMemory(&convert, sizeof(convert));
hDll = LoadLibrary(TEXT("DyCallClassOn3rdDll.dll"));
if (NULL != hDll) {
/// new class
/// 由于不知道sizeof(class), 需要new的大一些, 根据试验结果来
pClass = (CTestOnDllEx*)(new char[0x1000]);
if (NULL != pClass) {
/// 调用构造函数
// >> ??0CTestOnDll@@QAE@XZ == CTestOnDll::CTestOnDll
convert.pfnFarProc = GetProcAddress(hDll, TEXT("??0CTestOnDll@@QAE@XZ"));
if (NULL != convert.pfnFarProc) {
(pClass->*(convert.PFN_CTestOnDllEx))();
}
/// 调用类方法
// >> ?Add@CTestOnDll@@UAEHHH@Z == CTestOnDll::Add
convert.pfnFarProc = GetProcAddress(hDll, TEXT("?Add@CTestOnDll@@UAEHHH@Z"));
if (NULL != convert.pfnFarProc) {
printf("(pClass->*(convert.PFN_CTestOnDll_Add))(1, 2) = %d\n",
(pClass->*(convert.PFN_CTestOnDll_Add))(1, 2));
}
// >> ?Sub@CTestOnDll@@QAEHHH@Z == CTestOnDll::Sub
convert.pfnFarProc = GetProcAddress(hDll, TEXT("?Sub@CTestOnDll@@QAEHHH@Z"));
if (NULL != convert.pfnFarProc) {
printf("(pClass->*(convert.PFN_CTestOnDll_Sub))(1, 2) = %d\n",
(pClass->*(convert.PFN_CTestOnDll_Sub))(1, 2));
}
// 调用析构函数
// >> ??1CTestOnDll@@UAE@XZ == CTestOnDll::~CTestOnDll
convert.pfnFarProc = GetProcAddress(hDll, TEXT("??1CTestOnDll@@UAE@XZ"));
if (NULL != convert.pfnFarProc) {
(pClass->*(convert.PFN__CTestOnDllEx))();
}
// delete class*
delete [] (char*)pClass;
pClass = NULL;
}
/// 释放DLL
FreeLibrary(hDll);
}
}
试验用的DLL代码
假设这个DLL代码就是第三方的源代码, 我们是没有的
/// @file MyDll.h
#ifdef DYCALLCLASSONOURDLL_EXPORTS
#define DYCALLCLASSONOURDLL __declspec(dllexport)
#else
#define DYCALLCLASSONOURDLL __declspec(dllimport)
#endif // #ifndef DYCALLCLASSONOURDLL_EXPORTS
/// 假设这个导出DLL是第三方做的, 没有CreateClass和DesktoryClass导出函数
class DYCALLCLASSONOURDLL CTestOnDll {
public:
CTestOnDll();
virtual ~CTestOnDll();
virtual int Add(int iLeft, int iRight);
int Sub(int iLeft, int iRight);
};
/// @file MyDll.cpp
#include "stdafx.h"
#include <stdio.h>
#include "MyDll.h"
CTestOnDll::CTestOnDll() {
printf("CTestOnDll::CTestOnDll()\n");
}
CTestOnDll::~CTestOnDll() {
printf("CTestOnDll::~CTestOnDll()\n");
}
int CTestOnDll::Add(int iLeft, int iRight) {
return (iLeft + iRight);
}
int CTestOnDll::Sub(int iLeft, int iRight) {
return (iLeft - iRight);
}