我想在一个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