将仿函数作为函数指针传递

dag*_*agw 41 c c++ functor

我正在尝试在C++应用程序中使用C库,并在以下情况下找到了自己(我知道我的C,但我对C++很新).在C方面,我有一组函数,它们以函数指针作为参数.在C++方面,我有一个带有仿函数的对象,它与C函数所需的函数指针具有相同的签名.有没有办法使用C++仿函数作为函数指针传递给C函数?

Tom*_*icz 53

您不能直接将指向C++仿函数对象的指针作为指向C代码的函数指针(甚至是C++代码).

另外,为了将回调移植到C代码,它至少需要声明extern "C"为非成员函数.至少,因为某些API需要特定的函数调用约定,因此需要额外的声明修饰符.

在许多环境中,C和C++具有相同的调用约定,仅在名称修改方面有所不同,因此任何全局函数或静态成员都可以使用.但是你仍然需要operator()在正常的函数中包含调用.

  • 如果你的仿函数没有状态(它只是满足一些形式要求的对象):

    class MyFunctor {
      // no state
     public:
      MyFunctor();
      int operator()(SomeType &param) const;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    你可以编写一个普通的extern"C"函数来创建函子并执行它的operator().

    extern "C" int MyFunctorInC(SomeType *param)
    {
      static MyFunctor my_functor;
      return my_functor(*param);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果您的仿函数具有状态,例如:

    class MyFunctor {
      // Some fields here;
     public:
      MyFunctor(/* some parameters to set state */);
      int operator()(SomeType &param) const;
      // + some methods to retrieve result.
    }
    
    Run Code Online (Sandbox Code Playgroud)

    并且 C回调函数采用某种用户状态参数(通常为void*):

    void MyAlgorithmInC(SomeType *arr,
                        int (*fun)(SomeType *, void *),
                        void *user_state);
    
    Run Code Online (Sandbox Code Playgroud)

    你可以编写一个普通的extern"C"函数,它将状态参数转换为你的仿函数对象:

    extern "C" int MyFunctorInC(SomeType *param, void *user_state)
    {
      MyFunctor *my_functor = (MyFunctor *)user_state;
      return (*my_functor)(*param);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    并像这样使用它:

    MyFunctor my_functor(/* setup parameters */);
    MyAlgorithmInC(input_data, MyFunctorInC, &my_functor);
    
    Run Code Online (Sandbox Code Playgroud)
  • 否则唯一正常的方法(正常情况,如"在运行时不生成机器代码"等)是使用一些静态(全局)或线程本地存储将仿函数传递给extern"C"函数.这限制了你可以用你的代码做什么,并且很丑陋但会起作用.


And*_*nck 7

我发现这个" 宝石 "使用谷歌.显然可能,但我肯定不会推荐它.直接链接到示例源代码.

  • 哎呀,这确实是"黑魔法"作为提交它的类别名称所暗示的 (3认同)

Ale*_*tov 5

不,当然.C函数的签名将参数作为函数.

void f(void (*func)())
{
  func(); // Only void f1(), void F2(), ....
}
Run Code Online (Sandbox Code Playgroud)

所有带仿函数的技巧都由模板函数使用:

template<class Func>
void f (Func func)
{
    func(); // Any functor
}
Run Code Online (Sandbox Code Playgroud)