2010-05-28 4 views

답변

0

이식성있는 방법이 있는지 여부를 명확히 말할 수는 없지만 일반적으로 정적 메서드를 만들어 클래스 메서드에 대한 외부 액세스를 제공하는 것이 좋습니다. 그렇지 않으면 당신이 성공하더라도 당신은 그 클래스 구현에 대한 어플리케이션의 매우 단단한 결합을 만들 것입니다.

3

아니요, 멤버 함수 포인터는 a variety of sizes (플랫폼에 따라 4-16 바이트 이상, 기사의 표 참조) 일 수 있으며 정수 공간 내에 안정적으로 들어갈 수 없습니다. 이것은 가상 함수와 상속으로 인해 컴파일러가 여러 함수를 호출하여 올바른 함수를 호출 할 수 있기 때문에 단순한 주소가없는 경우가 있기 때문입니다.

0

이것이 의심스러운 경우 증분 링크를 해제하십시오. 그 동안 올바른 답을 얻고 있습니다.

다른 내 생각에 TestFuncvirtual 일 수 있습니다. 주소가 찍힌 가상 함수의 경우 VC++은 vtable 조회를 수행하는 약간의 썽크를 가짜로 만들고 해당 썽크에 대한 포인터를 주소로 제공합니다. (실제 파생 된 파생 된 형식의 경우 파생 된 올바른 함수를 찾을 수 있습니다.이 작업을 수행하는 다른 방법이 있지만이 포인터를 단일 포인터 수 및 호출 코드를 단순화 할 수 있습니다. 점프 할 때 점프.) 프로그램의 어셈블리 언어 출력을 켜고 결과를 살펴 봅니다. 무슨 일이 일어나고 있는지 분명해야합니다.

여기서도 올바른 대답을 얻을 수 있으며 '실제'기능의 주소를 찾을 방법이 없습니다. 실제로, 가상 함수는 하나의 실제 함수를 명명하지 않고, 파생 된 함수가 문제의 객체에 적합한 지 여부를 지정합니다. (이 동작이 마음에 들지 않으면 함수를 가상이 아닌 것으로 만드십시오.) 실제 함수의 실제 주소가 실제로 필요한 경우 두 가지 옵션이 있습니다.

성가신 하나는 함수의 vtable 인덱스를 찾기 위해 썽크를 검사하는 코드를 작성하는 것입니다. 그런 다음 해당 객체의 vtable을보고 해당 함수를 가져옵니다.

(하지만 비 가상 함수의 주소를 사용하면 호출 할 실제 함수의 주소를 알 수 있으며 썽크가 아니라는 점에 유의하십시오. 따라서이 가능성도 고려해야합니다. 가상 함수에 대한 포인터와 비가 상 함수에 대한 포인터는 동일합니다.)

더 쉬운 방법은 각 가상 함수에 대한 코드가 포함 된 비 가상 함수를 만든 다음 각 가상 함수가 비표준 함수를 호출하도록하는 것입니다. 가상 기능. 그것은 이전과 같은 행동을합니다. 그리고 코드가 어디에 있는지 알아 보려면 비 가상 함수의 주소를 가져옵니다.

(두 경우 모두이 작업을 잘 수행하기가 어려우며 성가신 일이 될 수 있으며 VC++에만 해당 될 수 있습니다. 그러나 노력을 기울이면 기꺼이 수행 할 수 있습니다. .)

+0

그것은 가상 아닙니다. 그것은 수입이지만. – user230821

+0

증분 연결을 해제 한 다음 시도해보십시오. 이 경우 각 외부 함수는 jmp를 실제 주소로 처리하는 코드를 통해 호출됩니다. (변경되지 않은 모듈은 호출 당 하나가 아닌 externed 함수 당 하나의 픽스 업만 필요하기 때문에 이전 링킹에서 데이터를 더 잘 재사용 할 수 있습니다.) –

4

나는 이것이 오래되었다는 것을 알고있다. 그러나 의미있는 주제에 대한 대답이 없기 때문에 여기에 나는 간다.

먼저 몇 가지 사항을 고려해야합니다. C++의 멤버 함수 호출 규칙을 __thiscall이라고합니다. 이 규약은 __stdcall과 거의 동일하지만 유효 호출이 이루어지기 전에 ECX이 호출되는 객체의 this 포인터로 설정된다는 점이 중요한 차이점입니다.

이를 설명하고 동시에 귀하의 질문에 대답,의 클래스 AClass는 다음과 같이 선언 된 멤버 함수가 있다고 가정 해 봅시다하려면 int AClass::myFunction(int a, int b)을 우리가 aClassObject라는 AClass의 인스턴스를 가지고있다.

// declare a delegate, __stdcall convention, as stated above 
typedef int (__stdcall *myFunctionDelegate)(int a, int b); 
// here's the 'hackish' solution to your question 
char myFunctionPtrString[10]; 
sprintf(myFunctionPtrString, "%d", &AClass::myFunction); 
int myFunctionPtr = atoi(myFunctionPtrString); 
// now let's call the method using our pointer and the aClassObject instance 
myFunctionDelegate myFunction = (myFunctionDelegate)myFunctionPtr; 
// before we make the call, we must put a pointer to aClassObject 
// in ECX, to finally meet the __thiscall calling convention 
int aClassObjectPtr = (int)&aClassObject; 
__asm{ 
    mov ecx, aClassObjectPtr 
} 
// make the call! 
myFunction(2, 3); 

그리고 물론

는, 인스턴스 유형 AClass의 인스턴스가 될 수 있습니다 다음은 원시 포인터를 얻을 후 처음 요구와 aClassObjectAClass::myFunction 전화를 '시뮬레이션'무엇을 할 수있는 다소 hackish 방법 .

건배,

Zozel

관련 문제