0

我有一个 DLL,它由我没有创建的程序作为插件加载,其目的是替换指向程序内部数组中成员函数的指针,以为加载它的现有程序提供附加功能。

该程序(加载插件 dll)具有如下所示的源代码

//Core object that all objects inherit
class MObject
{
public:
    //variables

    //functions
}

enum ECmdIndex
{
    CMD_RUN = 0x0,
    //ect
    CMD_MAX = 0x500
}
//Global command list of command functions
typedef void (MObject::*CommandFunc)(SContext&, void*)
CommandFunc GCommands[CMD_MAX];

//Example command function
void MObject::funcCmdRun(SContext& context, void* result)
{
    //do stuff
}
GCommands[CMD_RUN] = &MObject::funcCmdRun;

//This is used to execute command functions
void MObject::ProcessCommand( SContext& context, void* result )
{
    //ect

    //Execute the command's function on this MObject
    //Here is where my function should replace the default one
    (this->*GCommands[context.cmdInd])(context, result);

    //ect
}

我的 DLL 相当简单。它主要是用DLL中的一个替换程序的GCommands数组中的一个命令函数。

//MObject structure is replicated exactly in the DLL
//This is neccesary because my plugin is going beyond the provided API
//And so this is becoming a bit "hacky"
class MObject
{
public:
    //variables

    //functions
}

typedef void (MObject::*CommandFunc)(SContext&, void*)

void MObject::MyCommandFunc(SContext& context, void* result)
{
    //do stuff
}

void onLoad()
{
    //Get a pointer to GCommands array
    CommandFunc** pGCommands = GetGCommandOffset();

    //Replaced the desired command function with the new one
    pGCommand[0x1B] = &MObject::MyCommandFunc;
}

一个简短的摘要:宿主程序调用一个成员函数指针。我的 DLL 应该使指针指向它自己的函数,并在主机应用程序调用该指针时执行使该函数可调用的必要操作。

问题是我的新命令函数从未输入过,并且该命令在程序中执行时不再执行任何操作。我至少会期待崩溃。我为代码固有的 hacky 外观道歉,但肯定有正确的方法来实现这一点吗?

4

1 回答 1

1

这里的根本原因似乎是违反了 ODR。您的宿主应用程序使用 MyCommandFunc 的一个实现(或根本没有实现)定义一个 MObject,而您的 DLL 用另一个定义它。您在这里尝试做的事情(在每个成员函数的基础上,通过函数指针数组覆盖类功能)真是太奇怪了,即使接近便携也永远不会工作。

如果您有一堆对 MObject 进行操作的命令,您可以将它们声明为采用 MObject 的非成员(或静态成员)函数,并拥有一个数组。(您可以改为将它们公开为 MObjectCommand 虚拟接口的实现,但看起来您不需要任何状态,因此这可能是不必要的。)

于 2013-06-10T12:48:55.053 回答