如何在C++中获取成员函数的绝对地址?(我需要这个来进行thunking。)
成员函数指针不起作用,因为我无法将它们转换为绝对地址(void *
)-- 我需要知道实际函数在内存中的地址,而不仅仅是相对于类型的地址。
如何在C++中获取成员函数的绝对地址?(我需要这个来进行thunking。)
成员函数指针不起作用,因为我无法将它们转换为绝对地址(void *
)-- 我需要知道实际函数在内存中的地址,而不仅仅是相对于类型的地址。
在MSVC(从MSVC 2005开始)中,存在一种语法可以获取成员函数的地址。但是这很棘手。此外,通过常规手段无法将获得的指针转换为其他指针类型。虽然仍然存在一种方法来实现这一点。
以下是示例:
// class declaration
class MyClass
{
public:
void Func();
void Func(int a, int b);
};
// get the pointer to the member function
void (__thiscall MyClass::* pFunc)(int, int) = &MyClass::Func;
// naive pointer cast
void* pPtr = (void*) pFunc; // oops! this doesn't compile!
// another try
void* pPtr = reinterpret_cast<void*>(pFunc); // Damn! Still doesn't compile (why?!)
// tricky cast
void* pPtr = (void*&) pFunc; // this works
传统的类型转换,即使使用 reinterpret_cast
,也无法正常工作,这可能意味着微软并不强烈推荐此类转换。
然而,您仍然可以尝试。当然,这完全取决于实现方式,您必须了解适当的调用约定以执行 thunking,并具备适当的汇编技能。
Func
是一个虚函数,可能会发生令人惊讶的事情。 - Raymond Chenvoid* pPtr = (void*&) pFunc;
是否可移植,但在gcc和msvs中可以工作。我最感兴趣的是为什么 (void*&) pFunc;
能够正常工作,但是 (void*) pFunc;
却不能工作?两者几乎是相同的,除了你添加了左值引用。你能解释一下为什么一个可以工作而另一个不能工作吗? 这行代码的意思是将 pFunc
的地址转换为 void
类型的指针,并将其赋值给 pPtr
。(void*&) pFunc
中的左值引用表示将 pFunc
强制转换为一个指向 void
类型的指针的引用,而 (void*) pFunc
只是将 pFunc
的值转换为 void
类型的指针,但没有改变 pFunc
本身的类型。使用左值引用是因为 pFunc
是一个函数指针,它本身是一个地址,如果没有使用左值引用,将无法直接将其强制转换为 void
类型的指针。因此,使用 (void*&) pFunc
可以使编译器知道我们要对指针进行修改,而不仅仅是对其值进行转换。 - Mr.Anubis试试这个。应该可以让你将任何东西转换为任何东西 :)
template<typename OUT, typename IN>
OUT ForceCast( IN in )
{
union
{
IN in;
OUT out;
}
u = { in };
return u.out;
};
那么
void* member_address = ForceCast<void*>(&SomeClass::SomeMethod);
对于仍在寻找如何获取函数内存地址(而不是跳转地址)的人,这是我的解决方案:
UINT32 RelativityToTrampoline = *(UINT32*)((UINT64)&Func + 1);
UINT64 RealFuncAddr = (UINT64)&Func + RelativityToTrampoline + 5;
void *
中。相反,我正在尝试获取成员函数的内存地址。无论我们是在谈论C
函数还是某个虚拟钻石多重虚拟继承函数的覆盖(或其他任何内容),都只有一个函数,并且它必须从某个地方开始存储在内存中,可以用void *
表示。所有其他传统成员函数指针带来的麻烦都是为了动态调度,而我不需要。 - user541686