2012-06-20 38 views
1

我試圖創建一個地圖使用__stdcall函數名和函數指針的。這裏是我目前得到我的函數指針:創建地圖__stdcall

typedef int (CALLBACK* InitializeDLL)(int,int); 
InitializeDLL initializeDLL = (InitializeDLL)GetProcAddress(hInstanceLibrary, "InitializeDLL"); 

,現在我的地圖:

map<string, int *__stdcall> mapInt; 
mapInt["InitializeDLL"] = initializeDLL; //throws error for "InitializeDLL cannot be assigned to entity of type int*" 

該錯誤正是我所期待的,但我需要在__stdcall前明顯增加一個類型。如果我刪除了「INT」在前面然後抱怨有:

Error: expected a type specifier 

如果我只嘗試創建與包含在前面的「INT」地圖對象之後,再編譯它,它拋出的錯誤:

error C2059: syntax error : '>' 

這沒有多大意義的我。那麼使用__stdcall作爲地圖類型的正確方法是什麼?添加在它前面的INT形跡可疑給我,但如果我不加它,然後它抱怨需要指定一個類型。

而且回調是__stdcall#定義,如果這是令人困惑的。

+0

http://stackoverflow.com/questions/8304582/how-to-store-functional-objects-with-difrent-signature-in-a-container-eg-std#8304694 –

+1

'__stdcall'不再是一個類型比'const'更重要。他們只是一種類型的修飾符。 –

回答

3

一個函數指針類型不限於單一功能。例如,您的InitializeDLL函數指針類型可以包含指向具有此簽名的任何函數的指針:int foo(int,int)

也許CallbackFunction將是該類型定義一個更好的名字,因爲它包含具有可用於回調簽名的所有功能:

typedef int (CALLBACK* CallbackFunction)(int,int); 
CallbackFunction initializeDLL = 
    (InitializeDLL)GetProcAddress(hInstanceLibrary, "InitializeDLL"); 
map<string, CallbackFunction> mapInt; 
mapInt["InitializeDLL"] = initializeDLL; 

有更通用的方式來處理函數(甚至會員功能)。如果您能夠/願意使用新的C++ 11功能,則可以使用std::functionstd::bind。如果沒有,那麼你可以使用boost::functionboost::bind。這些工具的Boost和C++ 11版本的使用方式完全相同。 Boost文檔比cppreference更有幫助。

如果您向我們展示如何打算在地圖中調用回調函數(包括函數簽名不同的情況),我可能會向您展示如何使用functionbind作爲例子的示例。


你可能會考慮讓所有的命令回調具有相同的函數簽名,然後讓每個回調是負責提取他們需要做的工作任何參數。包含命令參數的對象可以作爲參數傳遞給回調函數。

您還可以考慮以std::vector<boost::any>std::vector<boost::variant>的形式向您的回調函數傳遞參數列表。回調函數然後將每個boost::anyboost::variant轉換爲與該特定參數關聯的特定類型。如果命令參數類型是簡單的內置類型,則甚至可以使用std:vector<UnionOfPossibleParameterTypes>,其中UnionOfPossibleParameterTypes是普通的舊式C風格union

+0

這更符合我的想法,但我仍然會針對不同的返回類型和參數配置做出很多CallbackFunction的變體。有沒有通用的方式指向我製作的任何CALLBACK * typedef? –

+0

@Atlos:查看更新後的答案。 –

+0

爲了時間上的利益,我去了將每個函數名字符串與已知函數列表進行手工比較,然後選擇適當的命令。我會在另一次採取更優雅的方式。 –

4

您正在使用__stdcall類似的,但它不是一個。你需要在地圖定義中使用你的函數指針類型。

map<string, InitializeDLL> mapInt; 

我不知道爲什麼你嘗試做擺在首位別的東西,因爲你已經在別處使用這種類型的,它不應該是很明顯的,這是需要在這裏呢?

+0

那麼這將是毫無意義的有一個與InitializeDLL的地圖,因爲那麼我將需要爲每個函數創建一個地圖,並在第一個地方打敗使用地圖的目的。我認爲__stdcall是獲得函數指針的一種方式,但正如聊天中向我解釋的那樣,它與嘗試傳遞類似'const'的東西沒有什麼不同。 –

+2

@Atlos:即使你可以使用'__stdcall'作爲類型,它是如何讓你比'void *'更接近?你仍然需要更多的信息才能真正使用指針。 – tenfour