动态调用没有源码的第三方DLL中的导出类

前言

假设第三方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);
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值