2014-04-13 48 views
4

在我的C++代碼中,我對C庫有一個依賴關係。這個C庫讓我用3個參數定義一個回調函數。例如:C++靜態成員函數作爲C回調需要訪問非靜態引用

file.c:

#ifdef __cplusplus 
extern "C"{ 
#endif 
    typedef void(*callback)(argument* 1, argument* 2, argument* 3); 
... 
    void set_callback(ARG1, callback name_of_callback); 
... 

在C++庫我開發我想此回調是一個類的成員函數,因爲我不能直接傳遞一個成員函數作爲回調C庫我創建了一個靜態函數作爲回調函數,在這個靜態函數中,我想引用一個類對象並調用它的成員函數來完成這個工作。

現在我的問題是,我的靜態函數需要有C庫指定的3個參數,所以我沒有找到一種方法來引用我在該靜態函數內開發的類的對象。我舉例想做的事:

MyClass.h:

class MyClass: 
public: 
    MyClass(); 
    void my_function(argument*1, argument* 2, argument* 3); 
    static void my_callback(argument* 1, argument* 2, argument*3); 

MyClass.cpp:

MyClass::MyClass(){ 
    set_callback(ARG1, my_callback); 
} 

void MyClass::my_function(argument*1, argument* 2, argument* 3){ 
     /* Do something */} 
void MyClass::my_callback(argument* 1, argument* 2, argument*3){ 
    Object->my_function(1, 2, 3); 
} 

之所以不設置類成員爲靜態的是,我希望能夠創建和銷燬此類的對象用於測試目的並控制測試中對象的狀態。

我正在使用g ++和gcc,希望有人可以提供一些幫助。 在此先感謝。

+3

它看起來像你的'set_callback'調用提供了稍後傳遞給回調的參數之一?通過該參數傳遞你的'MyClass *'。 –

回答

1

您可以創建一個靜態成員函數或一個純粹的 'C' 功能來做到這一點,可以考慮我下面的例子:

/** 
* C++ part 
*/ 
class obj 
{ 
public: 
    obj() {} 
    ~obj() {} 

    void doSomething(int a, int b) { cout << "result = " << a+b << endl; } 
}; 

/** 
* C Part 
*/ 
#ifdef __cplusplus 
extern "C" 
#endif 
{ 
typedef void (*callback)(void* one, void* two, void* three); 

callback g_ptr = NULL; 
void* arg = NULL; 

void c_lib_core (void) 
{ 
    printf ("C Lib core...\n"); 
    if (g_ptr) 
    { 
     g_ptr(arg, NULL, NULL); 
    } 
} 

void set_callback (void* arg, callback ptr) 
{ 
    g_ptr = ptr; 
} 

void my_callback (void* one, void* two, void* three) 
{ 
    obj* my_obj = (obj*) one; 

    my_obj->doSomething(1,2); 
} 

#ifdef __cplusplus 
} 
#endif 



int main (void) 
{ 
    obj a; 

    set_callback (&a, my_callback); 

    c_lib_core(); 
} 

輸出:

C Lib core... 
result = 3 

我將一個指向C++對象的指針作爲參數1傳遞給C++對象。這允許回調將它轉換回C++並調用它。 c_lib_core的東西就是這樣,我可以模擬回調函數的回調用於測試目的。這和全局變量一起在C代碼中。你只需要實現一個C函數並將ARG1設置爲你的對象,你就可以走了。

+0

我使用指向我的對象的全局指針,set_callback函數和my_callback實現了上述解決方案。 set_callback函數是從類構造函數的C++端調用的。我已經能夠在這個解決方案和下面的解決方案下通過相同的測試。我只是想知道關於內存使用情況,如果這個解決方案比靜態功能和類的靜態成員更好?目標是在資源非常有限的微控制器中使用此代碼。謝謝 – mgfernandes

+0

靜態成員應該使用與定義一次相同的內存。他們可能是vtptrs的入口,但不確定這是誠實的。如果他們的處理器是如此關心內存的話,或許純C就是要走的路,所以你不需要同時包含C和C++運行時庫,這些內存問題遠遠超過了幾個字節的內存問題 – Chris

0

假設沒有併發問題,我不知道是否是這種情況,更簡單的解決方案可能是定義一個靜態實例並在靜態函數中使用它。

就是這樣。

MyClass.h

class Object; 

class MyClass 
{ 
public: 
    MyClass(); 
    static Object* object; 
    static void callback(); 
    ~MyClass(); 

}; 

MyClass.cpp

Object* MyClass::object; 

MyClass::MyClass() 
{ 
    object = new Object(); 
} 

void MyClass::callback() { 
    object->sayHello(); 
} 

MyClass::~MyClass() 
{ 
    delete object; 
} 
+0

不將類成員設置爲靜態的原因是我希望能夠爲測試目的創建和銷燬此類的對象,並控制測試中對象的狀態。 – mgfernandes

+0

對不起。無論如何,你仍然可以創建和銷燬對象,並在測試中控制它們的狀態。爲什麼將類成員定義爲靜態可以防止這樣做? – perencia

+0

我想確保在test1上創建一個具有一個狀態(p.ex.對象具有ID = 1)的成員的MyClass,並且當事件發生時,回調執行成員函數,在test2上,我想創建一個MyClass成員處於另一個狀態(對象具有ID = 5),並且回調執行相同的成員函數。我的印象是聲明靜態對象,強制對象處於編譯時定義的狀態。 – mgfernandes

相關問題