Получить адрес памяти функции-члена?
Как получить абсолютный адрес функции-члена в С++? (Мне нужно это для thunking.)
Указатели функции-функции не работают, потому что я не могу преобразовать их в абсолютные адреса (void *
). Мне нужно знать адрес фактической функции в памяти, а не просто адрес по отношению к типу.
Ответы
Ответ 1
Существует синтаксис для получения адреса функции-члена в 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
Тот факт, что обычный приведение не работает, даже с reinterpret_cast
, вероятно, означает, что MS не рекомендует эту отливку очень сильно.
Тем не менее вы можете это сделать. Конечно, это зависит от реализации, вы должны знать подходящее соглашение о вызове для выполнения thunking +, чтобы иметь соответствующие навыки ассемблера.
Ответ 2
попробуйте это. должен позволять вам что-то притворяться:)
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);
Ответ 3
По умолчанию члены-члены С++ используют вызов __thiscall условность. Для того, чтобы объединить функцию-член, оба батута и обход должен иметь точно такое же соглашение о вызове, что и целевой функции. К сожалению, компилятор VC не поддерживает __thiscall, поэтому единственный способ создать законные функции объезда и батута - сделать их классными членами класса "обход".
Кроме того, С++ не поддерживает преобразование указателя в член функция к произвольному указателю. Чтобы получить необработанный указатель, адрес функции-члена должны быть перемещены во временную функцию-член указатель, затем передается, беря его адрес, затем де-ссылку на него.К счастью, компилятор оптимизирует код для удаления дополнительных операции указателя.
из библиотеки Microsoft Detour. Они имеют дело с инъекцией кода и обсуждают получение адреса невируальных функций-членов. Конечно, это специфический материал для реализации компилятора.
вы можете найти библиотеку здесь http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx