Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing member function pointer to the c-style function

I am trying to pass member function pointer to the c-style function (as it's lib in C)

The pointer it wants is defined as:

void (*)(int, const char*)

So the function I am trying to pass is:

void Application::onError(int error, const char *description)

I am trying to pass that with this code:

setCallback(bind(&Game::onError, this, placeholders::_1, placeholders::_2));

This gives me the following error:

cannot convert ‘std::_Bind_helper<false, void (Application::*)(Application*, int,
const char*), Application* const, const std::_Placeholder<1>&, const 
std::_Placeholder<2>&>::type {aka std::_Bind<std::_Mem_fn<void (Application::*)
(Application*, int, const char*)>(Application*, std::_Placeholder<1>,
std::_Placeholder<2>)>}’ to ‘GLFWerrorfun {aka void (*)(int, const char*)}’ for 
argument ‘1’ to ‘void (* glfwSetErrorCallback(GLFWerrorfun))(int, const char*)’
glfwSetErrorCallback(bind(&Application::onError, this, placeholders::_1, placeholders::_2));

Is there any way to successfully pass a member function as a bound function to the c-style function?

like image 247
petomalina Avatar asked Jan 23 '15 12:01

petomalina


People also ask

How pointers can be passed to function in C?

C programming allows passing a pointer to a function. To do so, simply declare the function parameter as a pointer type.

How do you get a pointer to member function?

The pointer to member operators . * and ->* are used to bind a pointer to a member of a specific class object. Because the precedence of () (function call operator) is higher than . * and ->* , you must use parentheses to call the function pointed to by ptf .

Can we call member function using this pointer?

Function pointer to member function in C++ In C++ , function pointers when dealing with member functions of classes or structs, it is invoked using an object pointer or a this call. We can only call members of that class (or derivatives) using a pointer of that type as they are type safe.

How do you call a member function from another member function in C++?

just make simple call like below................ class abc{ member_func1(); member_func2(); }; abc::member_func1(){ //.......................... this->member_func2();// just make simple call //............................ }


2 Answers

The result of std::bind is a complicated C++ object. It has to store all the bound arguments, for example. So it is most definitely not convertible to a pointer to function.

The callback specification you're dealing with apparently doesn't allow a "user data" payload, so there's nowhere to hide a pointer to a C++ object which you could use to invoke a non-static member funtion. This means you will have to call a global or static member function, or resort to a global/static member/per-thread variable to store the object pointer.

The only 100% portable way is to create a C linkage function to use as the callback. This does so, and uses a global object pointer to call your original onError():

Application *error_handling_application;

extern "C" void errorCallback(int error, const char *description)
{
  error_handling_application->onError(error, description);
}

Note that quite often, you will encounter programs which use a static member function in place of my errorCallback. This works with most compilers on most platforms, but it is not guaranteed to work. The C library expects a function with C language linkage. A static member function can only have C++ language linkage. It is possible for the calling mechanism of a C function and a C++ function to differ (depends on ABI), which would result in a malformed call to the static member function passed in.

like image 109
Angew is no longer proud of SO Avatar answered Oct 08 '22 08:10

Angew is no longer proud of SO


Since the member function also has the this pointer as implied argument, it is not of the type accepted by the C function. Hence, IMHO the only way is to generate a standalone function with C linkage

class A {
public: void func(int, const char*) const;
};

extern "C" {
  void cfunc(void(*)(int, const char*));
  void call_cfunc(const A*);
}

// in some source (non-header) file:
namespace {
  const A*pa;
  void afunc(int i, const char*s)
  { pa->func(i,s); }
}

void call_cfunc(const A*a)
{
  pa = a;
  cfunc(afunc);
}
like image 29
Walter Avatar answered Oct 08 '22 08:10

Walter