简体   繁体   English

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

[英]Is this a new method to get address of any function member?

"Member function" is the most stubborn thing. “成员职能”是最顽固的事情。 Simply I cannot convert them into *void values. 简而言之,我无法将它们转换为*void值。 I've done some methods which can solve this; 我已经做了一些方法可以解决这个问题。 however, the only thing I annoyed: I have to create a new definition for every set of argument types. 但是,我唯一烦恼的是:我必须为每组参数类型创建一个新定义。 So the fastest method to achieve the goal : 因此,实现目标的最快方法是:

struct FOO{

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

Firstly, calling a structure function member by assembly : 首先,通过程序集调用结构函数成员:

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

Longest : Template... 最长的:模板...

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; 
}

Shorter method : Define a function pointer to member function 较短的方法:定义一个指向成员函数的函数指针

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

But it's still too long. 但这还太长。

The most convenient method : Using directly standard function : sprintf 最方便的方法 :直接使用标准功能: sprintf

I discovered __thiscall functions also can be pushed as "..." parameters and I have checked it carefully by function printf . 我发现__thiscall函数也可以作为“ ...”参数推送,并且我已经通过函数printf仔细检查了它。 It is simple, and you don't need to define again its whole set of argument types to accept the pointer. 这很简单,您无需再次定义其整个参数类型集即可接受指针。 And the code : 和代码:

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);

As you can see this method is much shorter and also it's very convenient. 如您所见,此方法要短得多,而且非常方便。 I don't need to insert assembly code, the code looks better but on the other hand, I am worrying about speed. 我不需要插入汇编代码,代码看起来更好,但另一方面,我担心速度。 Can the code be compressed more? 可以进一步压缩代码吗? Suppose two commands now it only requires a single command to work, is this possible? 假设现在有两个命令只需要一个命令即可工作,这可能吗?

Unless your compiler is broken, you can't directly convert any function pointer, member of not, to void* . 除非编译器损坏,否则您不能将任何函数指针(不是not的成员)直接转换为void* On systems where non-member function pointers have the same size and format as non-member data pointers (required by Posix), you can do some fancy type punning: 在非成员函数指针的大小和格式与非成员数据指针相同(Posix要求)的系统上,可以执行一些特殊的类型调整:

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

This is undefined behavior according to the C++ standard, but will work on most von Neumann machines with linear addressing. 根据C ++标准,这是未定义的行为,但是可以在大多数具有线性寻址的冯·诺依曼机器上使用。 (It is likely to do strange things on Harvard architectures, or machines with non-linear addressing.) (这可能会在哈佛体系结构或具有非线性寻址的机器上做奇怪的事情。)

This only works when the types (original and target) have exactly the same size and format. 仅当类型(原始类型和目标类型)具有完全相同的大小和格式时,此方法才有效。 Pointers to member functions require additional information, which means that they almost never have the same size and format as normal function pointers, let alone data pointers. 指向成员函数的指针需要其他信息,这意味着它们几乎永远不会具有与普通函数指针相同的大小和格式,更不用说数据指针了。

I might add that none of the methods you describe actually work, in the sense that you can use the results in any way. 我可能会补充说,从某种意义上说,您可以以任何方式使用结果,因此您所描述的方法都无法真正起作用。

A pointer to member function can be cast to another pointer to member function type (per 5.2.10p10). 可以将指向成员函数的指针强制转换为另一个指向成员函数类型的指针(根据5.2.10p10)。 So, instead of void * , use void (*X::)() for some placeholder user-defined type X: 因此,代替void * ,对某些占位符用户定义类型X使用void (*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);

Whether this is useful depends on what you're planning to do with the cast pointer; 这是否有用取决于您打算对投射指针执行什么操作。 you can't call it without knowing the original type to cast it back to. 您必须在不知道原始类型后才能调用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM