2014-11-20 45 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