c++ visual-c++ memory-address member-functions

c++ - Obtener la dirección de memoria de la función miembro?



visual-c++ memory-address (3)

De forma predeterminada, las funciones de miembro de C ++ utilizan la convención de llamada __thiscall Para desviar una función miembro, tanto el trampolín como el desvío deben tener exactamente la misma convención de llamada que la función objetivo. Desafortunadamente, el compilador de VC no es compatible con un __thiscall, por lo que la única forma de crear desvíos legales y funciones de trampolín es convertirlos en miembros de una clase de "desvío".

Además, C ++ no admite la conversión de un puntero a una función miembro a un puntero arbitrario. Para obtener un puntero en bruto, la dirección de la función miembro se debe mover a un puntero de función miembro temporal, luego debe pasarse tomando su dirección y luego desvincularla. Afortunadamente, el compilador optimizará el código para eliminar las operaciones de puntero adicionales.

de la biblioteca de Microsoft Detour. Se ocupan de la inyección de código y discuten cómo obtener direcciones de funciones miembro no viruales. Por supuesto, es la implementación del compilador cosas específicas.

Puede encontrar la biblioteca aquí http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx

¿Cómo obtengo la dirección absoluta de una función miembro en C ++? (Necesito esto para thunk).

Los punteros de función de miembro no funcionan porque no puedo convertirlos en direcciones absolutas ( void * ). Necesito saber la dirección de la función real en la memoria, no simplemente la dirección relativa al tipo.


Existe una sintaxis para obtener la dirección de la función miembro en MSVC (a partir de MSVC 2005 IMHO). Pero es bastante complicado. Además, el puntero obtenido es imposible de convertir a otro tipo de puntero por medios convencionales. Aunque existe una manera de hacer esto sin embargo.

Aquí está el ejemplo:

// 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

El hecho de que el reparto convencional no funcione, incluso con reinterpret_cast probablemente signifique que MS no recomienda este reparto con mucha fuerza.

Sin embargo puedes hacer esto. Por supuesto, todo esto depende de la implementación, debe conocer la convención de llamada adecuada para realizar las tareas de Thunking + y tener las habilidades adecuadas para el ensamblador.


prueba esto. debería dejarte lanzar cualquier cosa a cualquier cosa :)

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

entonces

void* member_address = ForceCast<void*>(&SomeClass::SomeMethod);