这是获取任何函数成员地址的新方法吗?

2 c++ structure function member

"会员功能"是最顽固的事情.简单地说,我无法将它们转换为*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){}
};
Run Code Online (Sandbox Code Playgroud)

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

__asm mov ecx, ADDRESS_OF_STRUCTURE
__asm push //parameters
__asm call ADDRESS_OF_MEMBER_FUNCTION
Run Code Online (Sandbox Code Playgroud)

最长的:模板......

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; 
}
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

但它仍然太长了.

最方便的方法:直接使用标准函数: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);
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*nze 5

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

void (*fp)();
void * p = *reinterpret_cast<void**>( &fp );
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • @ H2CO3:确实如此.例如,`dlsym`返回`void*`,尽管它返回一个函数的地址. (2认同)