获取成员函数的内存地址?

Meh*_*dad 26 c++ member-functions memory-address visual-c++

如何在C++中获取成员函数的绝对地址?(我需要这个用于thunking.)

成员函数指针不起作用,因为我无法将它们转换为绝对地址(void *) - 我需要知道内存中实际函数的地址,而不仅仅是相对于类型的地址.

val*_*ldo 27

存在一种语法来获取MSVC中的成员函数的地址(从MSVC 2005 IMHO开始).但这很棘手.而且,所获得的指针不可能通过传统方式转换为其他指针类型.虽然有一种方法可以做到这一点.

这是一个例子:

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

传统铸件不起作用的事实,即使reinterpret_cast可能意味着MS不强烈推荐这种铸件.

不过你可以这样做.当然这是所有依赖于实现的,你必须知道适当的调用约定来进行thunking +具有适当的汇编技能.

  • 如果`Func`是一个虚函数,你可能会感到惊讶. (4认同)
  • @Raymond Chen:当然是"依赖于实现"和"不可移植".我提到了这一点.但这并不一定意味着应该**永远不要做.随意做,只要注意后果. (3认同)
  • 我不确定这行`void*pPtr =(void*&)pFunc;`是否可移植但是在gcc和msvs中有效.我最感兴趣的是知道为什么`(void*&)pFunc;`但是`(void*)pFunc;`不起作用?.两者几乎是相同的东西,除了你添加左值ref.你能解释为什么一个有效,另一个没有吗? (3认同)
  • 提前 7 年,它仍然有效......(在 Visual Studio 2019 上) (3认同)
  • 您所看到的是与实现相关的行为,并且不可移植.此技术可能随时停止工作.至于"为什么?" 这是因为成员函数指针不是函数指针.它们是奇怪的复杂事物. (2认同)

小智 5

尝试这个。应该让您将任何东西投射到任何东西

template<typename OUT, typename IN>
OUT ForceCast( IN in )
{
    union
    {
        IN  in;
        OUT out;
    }
    u = { in };

    return u.out;
};
Run Code Online (Sandbox Code Playgroud)

然后

void* member_address = ForceCast<void*>(&SomeClass::SomeMethod);
Run Code Online (Sandbox Code Playgroud)

  • @StephenEckels:我认为这个问题的*任何*答案都是C++标准未定义的行为(这很好,因为这个问题是特定于实现的)。 (3认同)