2013-05-10 266 views
0

我想獲取一個方法的地址(該方法稱爲EndScene)它是一個D3D9對象的函數,並將其分配給我的函數指針。初始化函數指針

但是,當我有我有麻煩它分配給我的函數指針的地址,這是我使用的代碼:

typedef HRESULT (IDirect3DDevice9::* EndSceneFunc)(void); 


    IDirect3DDevice9* pTempDev = ...; 
    // get the address of the virtual table 
    BYTE* pVtable = reinterpret_cast<BYTE*>(pTempDev); 
    // assign the address of the EndScene function to the function pointer (error) 
    EndSceneFunc endsceneFunc = pVtable + (sizeof(void*) * EndSceneIndex); 

我得到的錯誤是:BYTE類型的值*不能用於初始化EndSceneFunc類型的實體。

有誰知道如何解決這個問題?

編輯:我必須步行V表

回答

1

需要一個指針到成員函數,而不是函數的地址(假設是什麼存儲在虛函數表,並假設你的詭計實際上給你的V表項)。該語言提供一個簡單的方法來獲取:

EndSceneFunc endsceneFunc = &IDirect3DDevice9::EndScene; 

編輯:我必須步行V表

你不能,對不起做到這一點。你爲什麼認爲你需要這樣做?

我想在所有的修補它與我自己的函數

在這種情況下替換它,你不想要一個指針到成員函數,而你遠遠超越定義行爲的領域。你可以嘗試這樣的事:

// Reinterpret the pointer to the device as a pointer to a pointer 
// to a table of pointers, hoping that its first member is a pointer 
// to the vtable (which hopefully contains pointers to functions). 
void *** ppVtable = reinterpret_cast<void***>(pTempDev); 

// Indirect through that to get (hopefully) the pointer to the vtable 
void ** pVtable = *ppVtable; 

// Hopefully overwrite an element with a pointer to your function 
pVtable[EndSceneIndex] = reinterpret_cast<void*>(myFunction); 
+0

這實際上工作,謝謝,但我現在意識到即使犯了一個錯誤,我創建的pTempDev實際上應該分配給另一個進程已經創建的設備。這就是爲什麼我需要走虛擬表。你不能想到另一種解決方案嗎? – Jona 2013-05-10 18:21:38

+0

@JonathanD:我不知道你的意思,你根本不需要'pTempDev'來獲取指針,一旦你有了它,你就可以在任何'IDirect3DDevice9'上使用它。如果你的意思是你需要使用這個指針調用某個設備上的函數,那麼將它作爲'(device。* endsceneFunc)()'或一個指針('device-> endsceneFunc)()'在一個對象上調用。 – 2013-05-10 18:24:03

+0

我不想只是調用函數,我想修補它並用我自己的函數替換它。這就是爲什麼我認爲我需要走vtable,對吧? – Jona 2013-05-10 18:27:54

-1
EndSceneFunc endsceneFunc = pVtable + (sizeof(void*) * EndSceneIndex); 

這裏這條線是你的問題,因爲pVtable是BYTE *型的做到這一點。嘗試將其轉換爲EndSceneFunc的類型。

EndSceneFunc endsceneFunc = reinterpret_cast<EndSceneFunc>(pVtable + (sizeof(void*) * EndSceneIndex)); 
+1

這可能會強制它通過編譯器,但如果您嘗試使用它,則會遇到可怕的運行時錯誤。 – 2013-05-10 18:14:59

+0

是的,你真的應該試試Mike說的話,如果你想要的是指向一個特定的功能。我只是想解釋爲什麼你有錯誤。 – RandyGaul 2013-05-10 18:15:46

-1

這可能是一個普通的成員函數指針的初始化(從語法)在這種情況下,邁克·西摩的回答是一般,你會如何去做。如果你想要一個指向靜態成員函數的指針,那麼它是不同的,它具有普通的函數指針類型。

+0

當你說補丁是什麼意思?如果您想用相同的簽名將其更改爲同一類的不同成員函數,那麼您可以重新分配一個指向成員函數的指針,這是指向成員函數的全部指向點。如果你想把它改成帶有簽名HRESULT generic_function_name(IDirect3DDevice9 *)的函數,如果你感覺真的很勇敢,一些編譯器可能會接受它(不推薦)。 – OOhay 2013-05-10 20:10:40

+0

爲什麼downvote?在我添加這個時候,Mike Seymour的回答並不完整,並且沒有提到這個被稱爲成員函數的指針,據我所知,如果有人想進一步閱讀,這是非常有用的。 – OOhay 2013-05-13 10:09:33