2

“会员功能”是最顽固的东西。只是我无法将它们转换为*void值。我已经做了一些可以解决这个问题的方法;然而,唯一让我恼火的是:我必须为每组参数类型创建一个新定义。所以实现目标的最快方法:

struct FOO{

    void ONE_PARAM(int){}
    void TWO_PARAM(int, int){}
    void THREE_PARAM(int, int, int){}
    void FOUR_PARAM(int, int, int, int){}
};

首先,通过汇编调用结构函数成员:

__asm mov ecx, ADDRESS_OF_STRUCTURE
__asm push //parameters
__asm call ADDRESS_OF_MEMBER_FUNCTION

最长:模板...

template <class F,void (F::*Function)(int)>   //Note : Only for FOO::ONE_PARAM
void * GetFunctionAddress() {

    union ADDRESS  
    { 
        void (F::*func)(int);  
        void * function_address;  
    }address_data;  

    address_data.func = Function;  
    return address_data.function_address; 
}

更短的方法:定义一个指向成员函数的函数指针

void *function_address;
///////////////////////////////////////////////
void(FOO::*address_ONE_PARAM)(int) = FOO::ONE_PARAM;
void(FOO::*address_TWO_PARAM)(int, int) = FOO::TWO_PARAM;
void(FOO::*address_THREE_PARAM)(int, int, int) = FOO::THREE_PARAM;
void(FOO::*address_FOUR_PARAM)(int, int, int, int) = FOO::FOUR_PARAM;

__asm mov eax, address_ONE_PARAM //OK
__asm mov function_address, eax

__asm mov eax, address_TWO_PARAM //OK
__asm mov function_address, eax

__asm mov eax, address_THREE_PARAM //OK
__asm mov function_address, eax

__asm mov eax, address_FOUR_PARAM //OK
__asm mov function_address, eax

但是还是太长了。

最方便的方法:直接使用标准函数:sprintf

我发现__thiscall函数也可以作为“...”参数推送,我已经通过函数printf仔细检查了它。这很简单,您不需要再次定义它的整套参数类型来接受指针。和代码:

unsigned int address;
char buffer[12];
///////////////////////////////////////////////
sprintf(buffer, "0x%X", FOO::ONE_PARAM);
address = strtol(buffer,NULL,16);

sprintf(buffer, "0x%X", FOO::TWO_PARAM);
address = strtol(buffer,NULL,16);

sprintf(buffer, "0x%X", FOO::THREE_PARAM);
address = strtol(buffer,NULL,16);

sprintf(buffer, "0x%X", FOO::FOUR_PARAM);
address = strtol(buffer,NULL,16);

如您所见,这种方法要短得多,而且非常方便。我不需要插入汇编代码,代码看起来更好,但另一方面,我担心速度。代码可以压缩更多吗?假设现在有两个命令,它只需要一个命令就可以工作,这可能吗?

4

2 回答 2

5

除非您的编译器损坏,否则您不能直接将任何函数指针(not 的成员)转换为void*. 在非成员函数指针与非成员数据指针(Posix 要求)具有相同大小和格式的系统上,您可以做一些花哨的类型双关语:

void (*fp)();
void * p = *reinterpret_cast<void**>( &fp );

根据 C++ 标准,这是未定义的行为,但适用于大多数具有线性寻址的冯诺依曼机器。(它很可能在哈佛架构或具有非线性寻址的机器上做奇怪的事情。)

这仅在类型(原始和目标)具有完全相同的大小和格式时才有效。指向成员函数的指针需要额外的信息,这意味着它们几乎从不具有与普通函数指针相同的大小和格式,更不用说数据指针了。

我可能会补充一点,您描述的任何方法实际上都不起作用,因为您可以以任何方式使用结果。

于 2013-01-30T09:55:46.513 回答
0

指向成员函数的指针可以转换为指向成员函数类型的另一个指针(根据 5.2.10p10)。因此,void *使用void (*X::)()一些占位符用户定义类型 X 代替 :

struct X;
typedef void (*X::mem_fun_ptr_t)();

mem_fun_ptr_t mem_fun_ptr = reinterpret_cast<mem_fun_ptr_t>(&FOO::ONE_PARAM);
mem_fun_ptr_t mem_fun_ptr = reinterpret_cast<mem_fun_ptr_t>(&FOO::TWO_PARAM);
mem_fun_ptr_t mem_fun_ptr = reinterpret_cast<mem_fun_ptr_t>(&FOO::THREE_PARAM);
mem_fun_ptr_t mem_fun_ptr = reinterpret_cast<mem_fun_ptr_t>(&FOO::FOUR_PARAM);

这是否有用取决于您打算如何使用强制转换指针;在不知道将其转换回的原始类型的情况下,您无法调用它。

于 2013-01-30T10:20:07.640 回答