[英]How can I pass a C++ member function to a C API as a parameter
在我的C ++程序中,我需要調用以下c API:
GConn* gnet_conn_new (const gchar *hostname,
gint port,
GConnFunc func);
其中GConnFunc定義為:
void (*GConnFunc) (GConn *conn);
我的問題是我是否有C ++類並具有以下成員函數:
Class A {
public:
A();
void my_func (GConn* conn);
}
在我的A::A()
構造函數中,如何將this->myfunc
作為GConnFunc
參數傳遞給gnet_conn_new
?
謝謝。
大多數API提供指針大小的“用戶數據”參數,如下所示:
GConn* gnet_conn_new (const gchar *hostname,
gint port,
GConnFunc func,
void* user_data);
這將允許您在user_data中傳遞實例,並將C函數轉發給成員函數,如下所示:
void my_func(GConn *conn, void* user_data)
{
((MyClass*)user_data)->MyMemberFunc(conn);
}
也許您的API在某處具有替代或類似的“用戶數據”參數。 否則,沒有全局變量或靜態變量就無法真正做到這一點。
您可能需要包裝函數來處理此問題,或者可以使my_func靜態(假設它不需要訪問任何實例變量)。
簡短的答案,你不能。
長答案:
如果API有足夠的回旋余地,您需要調用該函數,就可以建立一個函數,您只需在該函數中注冊並作為中介調用即可。 通常,回調函數允許您包括傳遞給該函數的額外數據以及進行回調的對象生成的信息。 通常稱為“ client_data”之類的,其類型為void *或long。 在這種情況下,您可以簡單地使用此數據來包含足夠的信息,以在所需的實例上調用所需的函數,例如,將數據扔給boost :: function <>。
請注意,委派給您的成員函數的此中間函數可以是靜態成員或自由函數。
不幸的是,這里沒有這種選擇,因此您的工作將變得更加艱難。 您確實需要某種方法來確保為消息提供了正確的實例,並且您沒有辦法從回調的數據中識別該實例。 有兩種選擇可能對您不起作用:
確保您不要將多個實例用作回調目標。 使用跟蹤事件的一個實例來向該實例注冊某種類型的單例或全局實例。
注冊所需數量的實例,並確保它們都收到消息,然后處理該消息或不處理它。 您可能在這里使用了一種“責任鏈”,在這種情況下,目標可以有機會處理事件,然后返回一些信息,讓循環知道它應該繼續還是停止。
總之,沒有直接的方法可以做您想要的事情,但是如果您考慮選擇方案,可能會得到滿足您需求的答案。 用作提供給C API函數的回調的任何函數都必須引用為函數指針,而不是任何類型的成員指針……遺憾的是,它們也不是函子。 C不知道如何處理您的事情,因此您的回調必須是自由函數或靜態成員。
C ++類中的非靜態成員函數具有隱藏的“ this”參數。 如果您可以假設將其轉換為C,則該函數將轉換為:
void A_my_func (A * const this, GConn* conn);
盡管可以使用上面的原型編寫包裝函數並將其指針傳遞給C函數,但實際上並沒有一種方法可以自動在代碼中進行轉換。
處理此問題的常用方法是傳遞一個免費(非成員)函數或一個類靜態函數。 這兩種類型都沒有隱藏參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.