Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

passing functor as function pointer

Tags:

c++

c

functor

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?

like image 563
dagw Avatar asked Dec 03 '09 14:12

dagw


People also ask

What is the difference between a functor and a function pointer?

A function pointer allows a pointer to a function to be passed as a parameter to another function. Function Objects (Functors) - C++ allows the function call operator() to be overloaded, such that an object instantiated from a class can be "called" like a function.

How do you pass a functor as a template parameter?

One way to pass a functor is to make its type a template argument. A type by itself is not a functor, however, so the client function or class must create a functor object with the given type. This, of course, is possible only for class type functors, and it rules out function pointer types.

Is functor a function?

In functional programming, a functor is a design pattern inspired by the definition from category theory, that allows for a generic type to apply a function inside without changing the structure of the generic type. Simple examples of this are Option and collection types.

How do you pass a function pointer as a parameter in C++?

Passing a function as a parameter in C++ In this article, we will discuss different ways to design functions that accept another function as an argument. Passing pointer to a function: A function can also be passed to another function by passing its address to that function.


2 Answers

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.

like image 139
Tomek Szpakowicz Avatar answered Sep 28 '22 01:09

Tomek Szpakowicz


I found this "gem" using google. Apparently possible but I sure wouldn't recommend it. Direct link to example source code.

like image 22
Andreas Brinck Avatar answered Sep 28 '22 01:09

Andreas Brinck