2015-11-06 170 views
1

對於我正在嘗試編寫的應用程序,我需要能夠在interface中寫入GLEnable(GL_REPEAT)(得到這個工作)。一旦用戶這樣做,系統應該用正確的參數調用該函數。帶參數的Void *函數

對於這一點,我使用以下變量來獲得正確的功能:

std::map<std::string, void(*)(GLenum)> glEnableDisable;

並通過存儲在它的數據:

glEnableDisable["glEnable"] = glEnable; 
glEnableDisable["glDisable"] = glDisable; 

(注意上面給出警告「'='不能從'void(__stdcall *)(GLenum)'轉換爲'void(__cdecl *)(GLenum)'」)

最後,調用函數通過:

((void (*)(GLenum)) Main.glEnableDisable[SplittedUp[0]])(Parameter); 

現在,我不知道我做錯了。我有這個沒有參數工作正常,但我真的需要這個參數。

由於提前,

喬伊

+0

這是從來沒有真正的「工作正常」不帶參數。你很幸運,你沒有因爲使用錯誤的調用約定而崩潰('__stdcall'與'__cedcl') – PaulMcKenzie

+0

__stdcall來自Visual Studio給出的警告。它不是我的代碼的一部分(我試圖從OpenGL調用glEnable函數) –

+0

忽略警告給自己的危險。你應該問自己(或者stackoverflow)什麼是__stdcall什麼是__cdecl,爲什麼VS會警告我甚至不在我的代碼中的東西?甚至在嘗試運行任何東西之前。 –

回答

2

更改此:

std::map<std::string, void(*)(GLenum)> glEnableDisable; 

這樣:

std::map<std::string, std::function<void(GLenum)>> glEnableDisable; 

,再也不用擔心再次調用約定。一個std::function能夠存儲任何函數或可調用對象,無論它的調用約定是什麼。不需要

演員:

Main.glEnableDisable[SplittedUp[0]])(Parameter); 
+0

謝謝:)這使得void *函數非常容易o.o –

0

的問題是「如何店std::map<std::string, void(*)(GLenum)>接受參數的函數指針」?如果是,那麼答案是:這是不可能的,因爲你聲明瞭一個具有固定函數指針簽名的映射。並且代碼中的簽名是,存儲的函數指針不接受任何參數。

如果你想存儲的參數,那麼你有兩個選擇:

  1. 訪問該參數不超過棧和調用指定的函數所提供的參數,包裝函數。

  2. 爲您正在使用的每個函數指針簽名創建一個映射。

提示:幸運的是,由於錯誤的調用約定,程序沒有崩潰。建議將呼叫約定修改爲__cdecl

+0

應該在映射中的函數都使用FunctionName(GLenum)簽名(如果我沒有誤解你的話)。我可以使用什麼地圖來正確存儲簽名?該地圖只包含2個函數,glDisable和glEnable,儘管爲了整潔起見,我寧願不使用if語句來找出它是哪一個。 –

+0

@JoeyvanGangelen:不幸的是它不可能。容器(例如std :: map)只接受指定的簽名。每個參數和它的數據類型都會改變簽名。如果你想使它通用,你沒有別的選擇選擇1.另一個解決方案是一個工作線程,它讀取ab命令enum和一個通用數據結構來存放每個參數。在switch/case模塊中,你可以識別命令並提取參數傳遞給函數。我知道沒有優雅的解決方案,但它會工作。 –

0

很明顯:

void(*)(GLenum) 

正確的原型爲GLenum功能。

此處假定調用約定爲C,在Visual Studio中默認爲__cdecl。但是,您要調用的實際功能使用不同的調用約定,即__stdcall

像這樣的東西應該解決的問題:

typedef void (__stdcall *GLenumFunc)(int, int); // or whatever your params are 
//... 
std::map<std::string, GLenumFunc> glEnableDisable; 

至於調用約定是什麼:Calling Conventions on x86 platforms