2017-08-03 141 views
1

设置:我建立有部分C中的建筑和部分C++。如何通过功能从C到C++的参数和回C

以我体系结构I具有:

  1. 甲data_io(C)它获取的数据发送到处理器回调并输出处理的数据。
  2. 甲data_processor(C),其负责处理数据和按需变化。
  3. 甲settings_manager(C++),它决定使用哪个处理器。

的关系如下:

  1. 的settings_manager对象被实例化,其内部初始化与一个默认处理器功能的data_processor,然后初始化data_io发送给它的processing_callback_function(在settings_manager定义,但内部引用data_processor函数),然后在data_io启动时用它来处理数据。 (所以,在data_io在初始化接收processing_callback_function只有一次,不关心什么回调里面呢,它只是生成数据,调用processing_callback_function和输出处理后的数据)
  2. 当系统工作时,settings_manager可以决定改变处理的data_processor类型,所以它改变了processing_callback_function调用不同的data_processor功能(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(&设定管理:: processing_callback_function);

我得到以下错误:

"Incompatible pointer types 'ProcessorCallback_t' and 'void(Engine::*)(float*,int)'" 

嘛错误是显而易见的,该类型是不同的,因为第二个是一个成员函数,是对象的实例的一部分。

我读过,我应该使processing_callback_function静态,但我不知道它是否是正确的方法。

  1. 什么是处理这类事情的适当方式,是否有任何可能有用的读者或可能相关的编码策略?
+3

C中的_parts(为了获得最佳性能,没有类转换或多个耗时的内存解析)_你对C++的假设是错误的。 – 2017-08-03 19:25:31

+0

你是如何编译这些文件的,'SettingsManager'的定义是什么? – dbush

+0

@ manni66请解释我渴望学习,可能回答我的第二个问题 – alexm

回答

1

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_callbackCls静态方法和方式,将有机会获得的Cls私有成员:

class Cls { 
public: 
    static void Cls_callback(void* ptr) { 
     Cls* self = reinterpret_cast<Cls*>(ptr); 
     self->i += 1; 
    } 
private: 
    int i; 
}; 

但请记住,这实际上是一个UB。它会起作用,它比变种2少一点代码,但从技术上讲,标准并不能保证这会起作用。

P.S.再一次,不要混合风格。无处不在使用C++。

2

非静态类方法有一个隐藏的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(); 
    ... 
}; 

设置s_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); 
    ... 
}