设置:我正在构建一个架构,该架构的部分是C,部分是C++。
在我的架构中,我有:
- 获取数据的 data_io(C( 将其发送到处理器回调并输出处理后的数据。
- data_processor(C( 负责处理数据并按需更改。
- 决定使用哪个处理器的settings_manager(C++(。
关系如下:
- settings_manager对象被实例化,在它内部使用默认处理器函数初始化data_processor,然后初始化data_io向其发送processing_callback_function(在settings_manager中定义,但在内部引用data_processor函数(,然后在data_io启动时用于处理数据。(所以,data_io在初始化时只接收一次processing_callback_function,并不关心回调在里面做什么,它只是生成数据,调用processing_callback_function并输出处理后的数据(
- 当系统工作时,settings_manager可能会决定更改处理的data_processor类型,因此它会更改调用不同data_processor函数的processing_callback_function。(data_io不知道并继续工作(
以下是基本实现:
data_io.c:
typedef void (* ProcessorCallback_t)(float *, int);
ProcessorCallback_t processorCallback;
data_io_init(ProcessorCallback_t callback) {
processorCallback;
...init all other stuff like data pointer...
}
data_io_loop() {
bufSize = readData(&data);
processorCallback(&data, bufSize);
writeData(&data, bufSize);
}
data_procesor.c:
void data_processor_init() {
...initialization routine...
}
void data_processor_proc1(float *data, int bufSize) {
...data process...
}
void data_processor_proc2(float *data, int bufSize) {
...data process...
}
settings_manager.cpp:
void SettingsManager::start() {
data_processor_init();
this->processing_function = &data_processor_proc1;
//THIS IS MY QUESTION! HOW TO PASS THE processing_callback_function TO data_io_init
data_io_init(&SettingsManager::processing_callback_function);
... here starts a new thread to run loop below...
//while(this->condition) {
// data_io_loop();
//}
}
void SettingsManager::changeProcessorType(int processorType) {
switch(processorType) {
case 1:
this->processing_function = &data_processor_proc1;
break;
case 2:
this->processing_function = &data_processor_proc2;
break;
}
}
void SettingsManager::processing_callback_function(float *data, int buffer_size) {
this->processing_function(data, buffer_size);
}
我的问题:
1. 如何将processing_callback_function C++成员函数传递给 data_io_init C 函数?
当我执行以下操作时:
data_io_init(&SettingsManager::p rocessing_callback_function(;
我收到以下错误:
"Incompatible pointer types 'ProcessorCallback_t' and 'void(Engine::*)(float*,int)'"
好吧,错误是显而易见的,类型是不同的,因为第二个是成员函数,并且是对象实例的一部分。
我读过我应该将processing_callback_function设为静态,但我不确定这是否是正确的方法。
- 处理这类事情的适当方法是什么,是否有任何读者可能对阅读有用,或者编码策略可能相关?
非静态类方法具有独立函数没有的隐藏this
指针。 因此,您不能传递需要独立函数的非静态类方法。
在这种情况下,最好的解决方案是允许C++代码将用户定义的值传递给 C 代码,然后让 C 代码将该值传递回C++代码。 这样,C++代码就可以传递其this
指针。 例如:
data_io.h:
typedef void (* ProcessorCallback_t)(float *, int, void *);
void data_io_init(ProcessorCallback_t callback, void *userdata);
void data_io_loop();
data_io.c:
ProcessorCallback_t processorCallback;
void *processorUserData;
void data_io_init(ProcessorCallback_t callback, void *userdata) {
processorCallback = callback;
processorUserData = userdata;
...init other stuff as needed ...
}
void data_io_loop() {
...
processorCallback(&data, bufSize, processorUserData);
...
}
然后SettingsManager
可以这样做:
settings_manager.h:
typedef void (* ProcessorFunc_t)(float *, int);
class SettingsManager
{
private:
ProcessorFunc_t processing_function;
...
static void processing_callback_function(float *data, int buffer_size void *userdata);
public:
void start();
...
};
settings_manager.cpp:
#include "data_io.h"
void SettingsManager::start()
{
...
data_io_init(&SettingsManager::processing_callback_function, this);
...
}
void SettingsManager::processing_callback_function(float *data, int buffer_size void *userdata)
{
static_cast<SettingsManager*>(userdata)->processing_function(data, buffer_size);
}
或者这个(因为上面是技术上未定义的行为,但它确实适用于大多数编译器。以下是更符合标准(:
settings_manager.h:
typedef void (* ProcessorFunc_t)(float *, int);
class SettingsManager
{
...
public:
ProcessorFunc_t processing_function;
void start();
...
};
settings_manager.cpp:
#include "data_io.h"
void processing_callback_function(float *data, int buffer_size void *userdata)
{
static_cast<SettingsManager*>(userdata)->processing_function(data, buffer_size);
}
void SettingsManager::start()
{
...
data_io_init(&processing_callback_function, this);
...
}
1(用C++写下所有内容。使用 std::function 作为回调。这是处理此问题的最佳方法。您真的有性能问题吗?你测量过吗?C++并没有那么慢。混合两种语言样式会遇到的问题会带来更多问题。
2(C和C++中的函数相同。您始终可以执行以下操作:
class Cls {
public:
void callback() {}
};
void Cls_callback(void* ptr) {
reinterpret_cast<Cls*>(ptr)->callback();
}
然后将该Cls_callback
作为 C 回调传递。
3(您可以Cls_callback
成为静态Cls
方法,这样它就可以访问Cls
的私人成员:
class Cls {
public:
static void Cls_callback(void* ptr) {
Cls* self = reinterpret_cast<Cls*>(ptr);
self->i += 1;
}
private:
int i;
};
但请记住,这实际上是一个 UB。它将起作用,它的代码比变体 2 略少,但从技术上讲,标准并不能保证这将起作用。
附言再说一次,不要混合样式。随处使用C++。