2017-08-03 73 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); 
    ... 
}