Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to use a C library in a C++ app and have found my self in the following situation (I know my C, but I'm fairly new to C++). On the C side I have a collection of functions that takes a function pointer as their argument. On the C++ side I have objects with a functor which has the same signature as the function pointer needed by the C function. Is there any way to use the C++ functor as a function pointer to pass to the C function?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
289 views
Welcome To Ask or Share your Answers For Others

1 Answer

You cannot directly pass a pointer to a C++ functor object as a function pointer to C code (or even to C++ code).

Additionally, to portably pass a callback to C code it needs to be at least declared as an extern "C" non-member function. At least, because some APIs require specific function call conventions and thus additional declaration modifiers.

In many environments C and C++ have the same calling conventions and differ only in name mangling, so any global function or static member will work. But you still need to wrap the call to operator() in a normal function.

  • If your functor has no state (it is an object just to satisfy some formal requirements etc):

    class MyFunctor {
      // no state
     public:
      MyFunctor();
      int operator()(SomeType &param) const;
    }
    

    you can write a normal extern "C" function which creates the functor and executes its operator().

    extern "C" int MyFunctorInC(SomeType *param)
    {
      static MyFunctor my_functor;
      return my_functor(*param);
    }
    
  • If your functor has state, eg:

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

    and the C callback function takes some kind of user state parameter (usually void *):

    void MyAlgorithmInC(SomeType *arr,
                        int (*fun)(SomeType *, void *),
                        void *user_state);
    

    you can write a normal extern "C" function which casts its state parameter to your functor object:

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

    and use it like this:

    MyFunctor my_functor(/* setup parameters */);
    MyAlgorithmInC(input_data, MyFunctorInC, &my_functor);
    
  • Otherwise the only normal way to do it (normal as in "without generating machine code at runtime" etc.) is to use some static (global) or thread local storage to pass the functor to an extern "C" function. This limits what you can do with your code and is ugly but will work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...