C++에서의 일반적인 클래스의 메소드 번지 얻는 방법.
클래스 메소드 경우는 데이타 크기가 8바이트 짜리입니다. 즉 4바이트 포인트가 아니기 때문에,
일반 캐스팅이 되지 않습니다.
일반 함수는 그냥 번지 얻는 것이 매우 쉽지만, 클래스 메소드는
4바이트의 코드가 있는 번지와 4바이트의 인스턴스가 있는 데이타 번지로 구성된
형태의 데이타로만 얻어지므로, 여기서 필요한 번지를 취해 쓸수 있습니다.
메소드의 호출 번지 리스트를 만들려고 한다면 쓸수 있는 방법입니다.
그냥 눈요기꺼리입니다.
//---------------------------------------------------------------------------
class A
{
public:
void func()
{
Beep();
}
int add(int a) { return a + a; }
};
void test()
{
Beep();
}
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
// 일반 함수라면 이런 식으로 간단히 코드 번지를 얻을 수 있다.
void *test_func = test;
test_func;
// 클래스 경우.
A *a = new A;
// 정석으로 클래스 메소드의 실행 번지와 데이타 번지를 얻는 방법.
typedef void (__closure *TClassMethod0)(); // 메소드형 선언. 프로토타입 포함.
union
{
TClassMethod0 p;
//TMethod proc; // 이런식으로 오버랩 시켜 바로 proc.code로 위치를 알수도 있다.
} x;
x.p = (TClassMethod0)&a->func;
x.p(); // 실행.
void* code; // = x.proc.Code;
void* data; // = x.proc.Data;
TMethod *proc2 = (TMethod *)&x;
code = proc2->Code;
data = proc2->Data;
// cdecl 호출은 호출한 쪽에서 스택을 정리하므로
// 클래스 메소드는 숨겨진 0번째 인자로 그 객체 인스턴스의 데이타 영역 번지가
// 들어가게 되어 있다.
// 그것을 쓰지 않는다면 아래처럼 생략해도 된다.
asm call code; // 인자 없이 호출
asm // 0번째 인자 전달. cdecl 클래스 메소드 호출방법.
{
push data;
call code;
pop edx;
}
delete a;
}
//---------------------------------------------------------------------------
|