我有一个C库函数,需要一个函数指针用于回调,我想传入一个C++成员函数.C++函数修改了一个成员变量,所以我不能使用静态自由函数(如几个类似的帖子所示).我的尝试(如下所示)因编译器错误而失败.
这篇文章最接近我的要求:
如果没有静态函数,我怎么能这样做?谢谢!
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
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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*))’
Run Code Online (Sandbox Code Playgroud)
这是不可能的,至少有这个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);
}
Run Code Online (Sandbox Code Playgroud)
您需要一些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));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5222 次 |
| 最近记录: |