我有一个C库函数,它需要一个函数指针用于回调,我想传入一个C成员函数. C函数修改了一个成员变量,所以我不能使用静态自由函数(如几个类似的帖子所示).我的尝试(如下所示)因编译器错误而失败.
这篇文章最接近我的要求:
Using a C++ class member function as a C callback function
如果没有静态函数,我怎么能这样做?谢谢!
test.h
#ifndef TEST_H_ #define TEST_H_ #ifdef __cplusplus extern "C" { #endif typedef void (*handler_t)(int foo,void *bar); void set_handler(handler_t h); #ifdef __cplusplus } #endif #endif
test.c的
#include "test.h" #include <stdlib.h> static handler_t handler_ = NULL; void set_handler(handler_t h) { handler_ = h; } void handle_event(int foo,void *bar) { if (handler_ != NULL) handler_(foo,bar); }
TEST.CPP
#include "test.h" #include <iostream> using namespace std; class Foo { public: Foo() : ctr_(0) {}; // handler needs to access non-static variable,so it can't be static void handler(int foo,void *bar) { ++ctr_; } private: int ctr_; }; int main(int argc,char **argv) { // error: can't convert to "void (*)(int,void*)" set_handler(&Foo::handler); cout << "done" << endl; return 0; }
GCC barf
$gcc test.cpp test.c test.cpp: In function ‘int main(int,char**)’: test.cpp:18: error: cannot convert ‘void (Foo::*)(int,void*)’ to ‘void (*)(int,void*)’ for argument ‘1’ to ‘void set_handler(void (*)(int,void*))’
解决方法
至少使用handler_t签名是不可能的.
虽然您可以在.cpp上创建一个自由函数来包装成员调用,但您需要一个指向Foo实例的指针:
void my_wrap(int foo,void* bar) { Foo* some_foo_instance = ...; some_foo_instance->handler(foo,bar); } int main(int argc,char **argv) { set_handler(&my_wrap); }
您需要一些void *来将Foo实例作为处理程序属性传递:
// Header typedef void (*handler_t)(int foo,void *bar,void* arg1); void set_handler(handler_t h,void* arg1); // Impl. void set_handler(handler_t h,void* arg1) { handler_ = h; handler_arg1_ = arg1; } // cpp void my_wrap(int foo,void* bar,void* arg1) { Foo* some_foo_instance = static_cast<Foo*>(arg1); some_foo_instance->handler(foo,bar); } // main int main(int argc,char **argv) { Foo some_concrete_instance; set_handler(&my_wrap,static_cast<void*>(&some_concrete_instance)); }