2013-06-10 3 views
0

필자는 생성하지 않은 프로그램에 의해 플러그인으로로드되는 DLL을 가지고 있으며이 DLL의 목적은 프로그램 내의 배열에있는 멤버 함수에 대한 포인터를 추가 기능을 제공하기 위해 대체하는 것입니다 그것을로드하는 기존 프로그램에.DLL을 통한 멤버 함수에 대한 포인터 전달

이 프로그램은 (즉, 플러그인 DLL을로드)이

//Core object that all objects inherit 
class MObject 
{ 
public: 
    //variables 

    //functions 
} 

enum ECmdIndex 
{ 
    CMD_RUN = 0x0, 
    //ect 
    CMD_MAX = 0x500 
} 
//Global command list of command functions 
typedef void (MObject::*CommandFunc)(SContext&, void*) 
CommandFunc GCommands[CMD_MAX]; 

//Example command function 
void MObject::funcCmdRun(SContext& context, void* result) 
{ 
    //do stuff 
} 
GCommands[CMD_RUN] = &MObject::funcCmdRun; 

//This is used to execute command functions 
void MObject::ProcessCommand(SContext& context, void* result) 
{ 
    //ect 

    //Execute the command's function on this MObject 
    //Here is where my function should replace the default one 
    (this->*GCommands[context.cmdInd])(context, result); 

    //ect 
} 

내 DLL이 상당히 정직과 같은 소스 코드가 있습니다. 주로 프로그램의 GCommands 배열에있는 명령 함수를 DLL에있는 명령 함수로 대체합니다.

//MObject structure is replicated exactly in the DLL 
//This is neccesary because my plugin is going beyond the provided API 
//And so this is becoming a bit "hacky" 
class MObject 
{ 
public: 
    //variables 

    //functions 
} 

typedef void (MObject::*CommandFunc)(SContext&, void*) 

void MObject::MyCommandFunc(SContext& context, void* result) 
{ 
    //do stuff 
} 

void onLoad() 
{ 
    //Get a pointer to GCommands array 
    CommandFunc** pGCommands = GetGCommandOffset(); 

    //Replaced the desired command function with the new one 
    pGCommand[0x1B] = &MObject::MyCommandFunc; 
} 

요약 : 호스트 프로그램은 멤버 함수 포인터를 호출합니다. 내 DLL은 포인터가 자신의 함수를 가리 키도록해야하며, 호스트 응용 프로그램이 해당 포인터를 호출 할 때 해당 함수를 호출 가능하게 만들어야합니다.

문제는 내 새 명령 기능이 입력되지 않고 명령이 프로그램에서 실행될 때 더 이상 아무것도하지 않는다는 것입니다. 적어도 나는 충돌을 기대할 것입니다. 코드의 본질적인 해커 출현에 사과하지만 분명히 이것을 달성하는 올바른 방법이 있습니까?

+0

[this one]과 같은 질문을 발견했습니다. http : //stackoverflow.com/questions/1307278/casting-between-void-and-a-pointer-to- memember-function) 유용한 링크와 함께 포함 된 링크. 궁극적으로 그들은 내 문제를 해결하기에 충분하지 못했습니다. – Slight

+0

DLL 경계를 넘어서 사용되는 객체를 재정의하는 데 큰 문제가있을 것이라고 생각합니다! 그것은 공통 lib 또는 공통 헤더로 정의되어야합니다. 무엇을 성취하려고 노력하고 있으며 왜이 디자인을 고수해야만 하는가? – Dennis

+0

불행히도 MObject 클래스가 전혀 노출되지 않고 내부적으로 만 사용되므로이 메서드가 필요합니다. 플러그인 API는 아직 젊으며 많은 기능이나 유연성을 제공하지 않습니다. – Slight

답변

1

근본 원인은 ODR 위반으로 보입니다. 호스트 응용 프로그램은 MyCommandFunc를 구현 한 MObject를 정의합니다 (또는 전혀 구현하지 않음). 그리고 DLL은 다른 구현으로 정의합니다. 함수 포인터의 배열을 통해 멤버 함수 단위로 클래스 기능을 오버라이드 (override)하려고 여기에서 무엇을하려하는지는 별 나지 않지만, 이식성이없는 곳에서도 결코 작동하지 않습니다.

MObject에서 작동하는 많은 명령이있는 경우 MObject를 사용하는 비회원 (또는 정적 멤버) 함수로 선언 할 수 있으며 그 배열을 가질 수 있습니다. (대신 MObjectCommand 가상 인터페이스의 구현으로 노출시킬 수는 있지만 불필요한 상태가 필요하지는 않습니다.)

+0

질문에 약간의 오해가있을 수 있습니다. 나에 의해 작성되지 않았으므로 호스트 응용 프로그램의 코드를 제어 할 수 없습니다. 내 함수를 가리 키도록 호스트 응용 프로그램에서 포인터를 수정하는 호스트 응용 프로그램에 의해로드 된 DLL을 쓰고 있습니다. 문제는 필자의 함수가 호스트 프로그램에 의해 적절히 호출되도록하는 방법이다. 이것이 정규 함수 포인터라면 아무런 문제가 없을 것입니다. 또한 필자가 __declspec (벌거 벗은 채) 함수를 사용해야하고, 프롤로그 asm을 직접 작성하면 피 호출자 측에서 문제가있는 경우이를 수행 할 것입니다. – Slight

관련 문제