2013-08-27 110 views
0

我正在撰寫一個使用舊3D模型文件格式(Carbon Graphics'GEO,如果您感興趣的話)的模擬,以及該模型格式的OpenSceneGraph插件更新它的方式內部變量是通過註冊模型的回調方法在需要更新其值時進行調用。回調具有模擬時間,變量名稱和當前值。您將返回該變量的新值。回調方法無法訪問成員變量或實例

所以,在我的代碼,我設置回調如下:

headerNode->setUserUpdate(&FlightDriver::updateGeoVariable); 

類headerNode屬於有以下變量:

double (* uvarupdate)(const double t, const double val, const std::string name); 

每間隔,它會調用uvarupdate我在在

updateGeoVariable(const double time, const double val, const std::string name) 
{ 
    return flightData->getValue(name); 
} 

爲模型內的每個變量,一個:已設置爲我。我無法使方法或flightData成員爲靜態,因爲它們需要每個實例都是唯一的。

我有一種預感,這種回調可能是從C代碼調用,因爲當我打破,它似乎沒有知識,它是一個類裏面,如果我更改簽名,三個相同的值傳遞並首先插入任何參數。

但是,我真的需要訪問該類的成員,以避免一個非常髒的kludge。由於課程本身是驅動3D世界的模型,有兩個或更多的這些意味着我得到的回調是:「234,pitch,90」,我無法知道數據屬於哪個模型的變量。

我可能會重新編譯DLL(因爲它是一個OSG插件),另外需要一個指向該實例的指針,或者一個id或某個東西,然後在回調函數中返回它,但是我真的很想避免這種情況如果可能的話。

我已閱讀過有關thunking的內容,但看起來像這樣,大多數其他想法都需要訪問創建回調的代碼。有任何想法嗎?

回答

0

您需要傳遞指向方法的指針,但uvarupdate是指向函數的指針,它們是不同的類型。指向某個方法的指針包含隱式指向實例的this,它不適合函數指針。您需要以其他方式通過this

如果您不更改回調的簽名,則必須以某種方式計算實例(this)。如果可以從name參數中確定,那麼很容易。另一種方法是爲每個實例創建一個蹦牀。如果只有幾個實例,則可以爲每個實例編寫一個單獨的蹦牀函數。動態創建蹦牀(在運行時)非常棘手且不可移植:事實上,您需要將一些機器指令寫入RAM,以便他們使用正確的this參數調用您的方法。但也有可能,這就是一些圖書館所做的事情(例如Delphi中的VCL)。

+0

我從來沒有聽說過蹦牀。我會詳細閱讀。這仍然需要更改uvarupdate的簽名嗎?如果是這樣,我想我最終會試圖用我需要的附加功能自己重新編譯插件。 – drearyworlds

+0

蹦牀是一個調用C++方法的普通(非成員)函數。在這種情況下,不需要更改'uvarupdate'的簽名,只需將一個指向蹦牀的指針傳遞給'setUserUpdate'。但是對於每個類的實例,您將需要一個不同的蹦牀,這就是實例如何區分的。 – Inspired