我有一个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外观道歉,但肯定有正确的方法来实现这个目标吗?
答案 0 :(得分:1)
这里的根本原因似乎是ODR违规。您的主机应用程序使用MyCommandFunc的一个实现(或根本没有实现)定义一个MObject,并且您的DLL使用另一个实现定义它。你在这里尝试做什么(通过一系列函数指针在每个成员函数的基础上覆盖类功能)很奇怪,并且永远不会在可移植的情况下工作。
如果你有一堆在MObject上运行的命令,你可以将它们声明为带有MObject的非成员(或静态成员)函数,并且有一个数组。 (你可以将它们作为MObjectCommand虚拟接口的实现公开,但它看起来不像你需要任何状态,所以这可能是不必要的。)