使用C类成员函数(不能是静态的)作为C回调函数

前端之家收集整理的这篇文章主要介绍了使用C类成员函数(不能是静态的)作为C回调函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个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));
}

猜你在找的C&C++相关文章