我想在一個C++應用程序使用C庫,並發現我在下列情況下(我知道我的C,但我是相當新的C++)的自我。在C方面,我有一個函數集合,它將函數指針作爲它們的參數。在C++方面,我有一個函子的對象,它具有與C函數所需的函數指針相同的簽名。有沒有辦法將C++函數作爲函數指針傳遞給C函數?傳遞仿函數的函數指針
回答
您不能直接將指針傳遞給C++函數對象,作爲指向C代碼 (甚至是C++代碼)的函數指針。
此外,爲了便於將回調傳遞給C代碼,至少需要將 聲明爲extern "C"
非成員函數。至少,因爲一些API需要特定的函數調用約定,因此需要額外的聲明修飾符。
在許多環境中,C和C++具有相同的調用約定,並且在名稱修改中只有 ,因此任何全局函數或靜態成員都可以使用。 但是你仍然需要在正常的功能中打電話給operator()
。
如果你的仿函數沒有狀態(這是一個對象,只是爲了滿足一些正規 要求等):
class MyFunctor { // no state public: MyFunctor(); int operator()(SomeType ¶m) const; }
你可以寫一個普通的extern「C」,它創造了仿函數功能執行它的 運算符()。
extern "C" int MyFunctorInC(SomeType *param) { static MyFunctor my_functor; return my_functor(*param); }
如果你的仿函數有狀態,例如:
class MyFunctor { // Some fields here; public: MyFunctor(/* some parameters to set state */); int operator()(SomeType ¶m) const; // + some methods to retrieve result. }
和的C回調函數某種類型的用戶狀態參數(通常是無效*):
void MyAlgorithmInC(SomeType *arr, int (*fun)(SomeType *, void *), void *user_state);
你可以寫一個正常的extern「C」函數,將其狀態參數轉換爲 你的函數對象:
extern "C" int MyFunctorInC(SomeType *param, void *user_state) { MyFunctor *my_functor = (MyFunctor *)user_state; return (*my_functor)(*param); }
,並使用它是這樣的:
MyFunctor my_functor(/* setup parameters */); MyAlgorithmInC(input_data, MyFunctorInC, &my_functor);
否則,只有正常的方式做到這一點 (正常如在「不產生在運行時機器代碼」等) 是使用一些靜態(全局)或線程本地存儲將函子 傳遞給外部「C」函數。 這限制了你可以用你的代碼做什麼,而且很醜,但會起作用。
我不認爲你可以:operator()
在一個函數對象真的是一個成員函數,和C不知道這些事情。
,你應該能夠使用什麼是免費的C++函數,或者類的靜態功能。
這取決於如果這是一個靜態或實例方法,如果是靜態的,那麼你可以通過功能的className :: functionName,而如果它是一個實例方法是公平更加複雜,因爲你顯然需要配合在某些情況下,但不能以與在C#中的代表一樣的方式進行。
我發現這樣做的最好方法是創建一個持有類,該類使用實例化該對象以及函數指針,持有類可以直接調用該函數。
不,當然。 C函數的簽名採用參數作爲函數。
void f(void (*func)())
{
func(); // Only void f1(), void F2(), ....
}
與仿函數的所有招數都使用模板功能:
template<class Func>
void f (Func func)
{
func(); // Any functor
}
我會說不,因爲C++函數對象有一個重載的操作符()
這是一個成員函數,並會因此需要一個成員函數指針。與普通的C函數指針相比,這是一種完全不同的數據類型,因爲它不能在沒有類的實例的情況下調用。您需要將一個普通函數或靜態成員函數傳遞給C庫。由於過載的()
運算符不能是靜態的,所以你不能這樣做。您需要將C庫作爲普通非成員函數或靜態成員函數傳遞,然後您可以從中調用C++函子。
嗯,也許你可以寫一個免費的模板函數來包裝你的函數對象。如果他們都有相同的簽名,這應該工作。像這樣(未測試):
template<class T>
int function_wrapper(int a, int b) {
T function_object_instance;
return funcion_object_instance(a, b);
}
這將適用於所有采用兩個整數並返回int的函數。
請不要使用它。將你的函數包裝在一個常規的C函數中並不需要一個醜陋的黑客應該是微不足道的。 – 2009-12-03 18:03:37
yuck,這確實是「黑魔法」作爲它提交的類別名稱建議 – 0xC0000022L 2011-06-23 17:57:32
純寶石我認爲這是唯一的方法,因爲c調用者不知道如何推送額外的參數。函數是在具有這個「const」調用者的ram中創建的。 – 2013-04-10 19:38:24
用C++編寫A C回調函數必須被聲明爲extern "C"
功能 - 因此使用仿函數是直接的。你需要編寫一些包裝函數來用作回調函數,並讓包裝函數調用函子。當然,回調協議需要有一些將上下文傳遞給函數的方式,以便能夠到達函子,或者任務變得非常棘手。大多數回調方案都有一種方式來傳遞上下文,但我曾與一些沒有的腦死亡工作。
看到這個答案的一些細節(以及在傳聞證據的意見看回調必須extern "C"
,而不僅僅是一個靜態成員函數):
許多C採用函數指針回調的API具有用戶狀態的void *參數。如果你有其中一個,那麼你很幸運 - 你可以使用一個Exterm C函數,將用戶數據視爲某種引用或鍵來查找函數,然後執行它。
否則,沒有。
GCC允許你成員函數指針轉換爲純函數指針(由純函數指針調用的函數的第一個參數是然後this
)。
查看respective link in the manual。
這需要-Wno-pmf-conversions
標誌,以使相應的警告靜音以達到非常標準的功能。 C風格庫與C++風格編程接口非常方便。當成員函數指針是一個常量時,甚至不需要生成任何代碼:無論如何,API將使用該參數順序。
如果你已經有一個仿函數,以這種方式展平仿函數可能意味着將其展平爲operator()
,給你一個必須用函子類指針本身作爲第一個參數調用的函數。這並不一定有幫助,但至少有C鏈接。
但至少當你沒有通過函數時,這是有幫助的,並提供了一個從<functional>
std::mem_fn
一個不廢話的C聯動替換。
- 1. 從函數傳遞指針到函數
- 2. 將函數指針傳遞給函數
- 3. 傳遞隱函數指針
- 4. Ç傳遞指針函數
- 5. 傳遞函數指針
- 6. 函數指針 - 參數傳遞給一個函數指針
- 7. 指向函數或仿函數的指針?函數發生器
- 8. 函數:傳遞指向$ con的指針
- 9. c - 傳遞指向函數的指針
- 10. 如何將函數指針傳遞給函數內的函數
- 11. C:傳遞一個函數指針在它傳遞給函數
- 12. 將函數指針傳遞給函數+函數參數
- 13. c傳遞指針遞歸函數
- 14. 傳遞3D指針數組到函數
- 15. 將指針數組傳遞給函數
- 16. 傳遞函數指針作爲參數
- 17. 將數組指針傳遞給函數
- 18. 將參數傳遞給函數指針
- 19. 將指針數組傳遞給函數
- 20. 函數參數傳遞指針混亂
- 21. 傳遞函數指針作爲參數
- 22. 如何傳遞指向構造函數的函數指針?
- 23. 傳遞仿函數在C++
- 24. 帶指針的字符傳遞函數
- 25. 傳遞函數C++中的指針
- 26. 傳遞成員函數的指針
- 27. 傳遞指針的API函數
- 28. 傳遞枚舉函數的指針
- 29. 傳遞給函數頭的指針
- 30. 正確傳遞函數C++的指針
+1,詳細描述可能的情況。 – 2009-12-03 17:55:18
+1,雖然回調簽名絕對不是C :) – quinmars 2009-12-03 22:23:20
oops,nvm,不知何故,我混合了聲明,並認爲你在C中使用引用。 – quinmars 2009-12-03 23:24:49