Passing Functor as Function Pointer

passing functor as function pointer

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 ¶m) 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 ¶m) 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.

How to assign functor to function pointer?

In general, function objects contain additional context information besides the function to be called. About the only function object you can assigned to a function pointer is a lambda function with an empty capture but this is really just a function:

void (*bar)(int) = [](int x) { std::cout << x; }

If you want to get a function object through a function pointer, you need to hope that the function pointer has a suitable argument which is available for users to specify and which can passed through directly:

void call_function(int arg, void* user_data) {
(*static_cast<std::function<void(int)>*>(userdata))(arg);
}
...

std::function<void(int)> function_object;
void (*bar)(int, void*) = &call_function;

bar(17, &function_object);

Most reasonably modern interfaces taking a function pointer also take a user-data pointer which can be used to pass through the necessary context. Obviously, in addition to passing through the necessary context it may be necessary to somehow maintain the life-time of object used as context.

I'm not a Windows programmer but I would guess that the API you are trying to use actually has the ability to set both a function pointer and a pointer to some user data. If there is no place to pass through context information you would need to somehow encode the necessary information in the function pointer itself. For example, you could use a function pointer which references a global object to get the context. Clearly, you would need a different function for each context you want to pass.

function pointer vs functors in C++

For one, the functor can contain internal state; a state that is valid for this invocation of the function object only. You could add static variables to your function, but those would be used for any invocation of the function.

Second, the compiler can inline calls to the functor; it cannot do the same for a function pointer. This is why C++ std::sort() beats the crap out of C qsort() performance-wise.

C++ functor as a function pointer

No, you can't convert a class-type object to a function pointer.

However, you can write a non-member wrapper function that calls the member function on the right instance. Many APIs, including CreateThread, allow you to provide a pointer that it will give back to you when it calls your callback (for CreateThread, this is the lpParameter parameter). For example:

DWORD WINAPI FunctorWrapper(LPVOID p)
{
// Call operator() on the functor pointed to by p:
return (*static_cast<FunctorType*>(p))();
}

// Used as:
FunctorType f;
CreateThread(0, 0, &FunctorWrapper, &f, 0, 0);

Passing functors and function pointers interchangeably using a templated method in C++

If you want to get a function pointer for an overloaded function, you need to tell the system which function out of the overload set you want:

foo.bar(2, static_cast<void(*)(int)>(&Function);

In the quoted case the function is actually a template, i.e., you can also refer to its specialization directly:

foo.bar(2, &Function<int>);

function pointer to functor

It seems like you have no option other than writing your own functor as a derived type of Functor<int, int>. However, you could save yourself some trouble by providing an intermediate class template functor that can be instantiated from a functor or funciton pointer:

template<typename R, typename A>
struct GenericFunctor<R, A> : public Functor<R, A>
{
template <typename F>
MyFunctor(F f) : f_(f) {}
ReturnType operator()(A arg) = { return f_(arg);}
private:
std::function<R(A)> f_; // or boost::function
};

Then you can say

GenericFunctor<int, int> fun = foo;
API(&fun); // works. GenericFinctor<int,int> is a Functor<int,int>

This is just a workaround for the fact that the stuff you have been given is so awful.

Using operator new as a functor/function pointer

Why not something like this?

   std::allocator<foo> alloc;
do_something(std::bind(&std::allocator<foo>::construct<foo, int, std::string>, &alloc, alloc.allocate(sizeof(foo)), std::placeholders::_1, std::placeholders::_2), 12, "test2");

What are C++ functors and their uses?

A functor is pretty much just a class which defines the operator(). That lets you create objects which "look like" a function:

// this is a functor
struct add_x {
add_x(int val) : x(val) {} // Constructor
int operator()(int y) const { return x + y; }

private:
int x;
};

// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument

std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
assert(out[i] == in[i] + 1); // for all i

There are a couple of nice things about functors. One is that unlike regular functions, they can contain state. The above example creates a function which adds 42 to whatever you give it. But that value 42 is not hardcoded, it was specified as a constructor argument when we created our functor instance. I could create another adder, which added 27, just by calling the constructor with a different value. This makes them nicely customizable.

As the last lines show, you often pass functors as arguments to other functions such as std::transform or the other standard library algorithms. You could do the same with a regular function pointer except, as I said above, functors can be "customized" because they contain state, making them more flexible (If I wanted to use a function pointer, I'd have to write a function which added exactly 1 to its argument. The functor is general, and adds whatever you initialized it with), and they are also potentially more efficient. In the above example, the compiler knows exactly which function std::transform should call. It should call add_x::operator(). That means it can inline that function call. And that makes it just as efficient as if I had manually called the function on each value of the vector.

If I had passed a function pointer instead, the compiler couldn't immediately see which function it points to, so unless it performs some fairly complex global optimizations, it'd have to dereference the pointer at runtime, and then make the call.



Related Topics



Leave a reply



Submit