使用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++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...