2014-11-20 43 views
1

我有一个C API给数据源。要得到新的数据可用的通知,可以给API一个函数指针形式的回调函数;当数据进入你的回调会被调用API的报头包含这样的行:将实例方法传递给需要C函数指针的API

struct DataRecord { ... }; 
typedef void (*DataCallback)(DataRecord *data); 

void set_data_callback(DataCallback processor); 

我的C++类与签名

void MyClass::process_data(DataRecord *data); 

和MyClass的我的构造方法的实例方法d喜欢将新实例的process_data方法设置为C API的数据回调。继this answer我试着写这段代码在构造函数中:

typedef void (MyClass::data_callback_t)(DataRecord*); 
data_callback_t callback = &MyClass::process_data; 
set_data_callback(callback); 

当我这样做,我得到了错误

错误C2664:“set_data_callback”:无法从“data_callback_t”转换参数2“ DataCallback”

没有上下文中,这种转换是可能

(我使用Visual C++ 2010 Express,尽管我希望这没有什么区别。)

如何从实例和方法中提取C函数指针?

+1

简短的回答是,你不能。除非你准备硬编码哪个实例被调用,然后你可以有一个非成员,如'void process(DataRecord * data){someInstance-> process_data(data); }'。为了解决这个限制,你需要修改API来在注册回调时使用'void * stuff'。 – 2014-11-20 22:26:28

+0

这是一个非常糟糕的API,它不允许传递上下文指针...有一些非标准库在运行时创建trampolines,以及其他使用静态(或线程本地)变量的缺陷方法。 - - 如果函数在最后一次调用回调函数时没有返回,那么它就不那么可怕...... – Deduplicator 2014-11-20 22:37:20

回答

1

你不能。 MyClass::process_data可以被认为是void(MyClass*, DataRecord*),这是错误的类型。您必须以某种方式将您的班级指针包装到呼叫中。

一种方法可能是用静态指针引入类型:

struct MyClassCallbackHelper 
{ 
    static MyClass* myClass; 

    static void callback(DataRecord* record) { 
     myClass->process_data(record); 
    } 
}; 

所以,你可以这样做:

MyClassCallbackHelper::myClass = this; 
set_data_callback(&MyClassCallbackHelper::callback); 
+0

我相信这样的回调助手可以用于我的应用程序。谢谢! – bdesham 2014-11-20 22:53:56