簡體   English   中英

使用C ++類方法作為函數回調

[英]Using c++ class method as a function callback

我正在使用相機API,每次有新圖像時都會調用回調函數。 回調函數的傳遞方式為:

BOOL WINAPI StTrg_SetTransferEndCallback(HANDLE hCamera, funcTransferEndCallback func, PVOID pvContext);

其中funcTransferEndCallback為:

typedef void (WINAPI *funcTransferEndCallback)(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext);

我不想做一個回調函數,但實際上在類中使用了一個方法。 我在類的構造函數中調用此StTrg_SetTransferEndCallback() ,因此可以初始化相機並傳遞類的方法來捕獲每個新幀並進行處理。

我的方法在類.h中定義為:

public class Camera
{
public:
.....
void TakePicture(string pictureFileName);
void StartRecording(string videoFileName);
void StopRecording(void);
 .....
private:
volatile bool takePictureFlag;
volatile bool startRecordingFlag;
volatile bool stoptRecordingFlag;
void __stdcall TransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext);
};

如果我嘗試這樣做:

StTrg_SetTransferEndCallback(cameraHandle, TransferEndCallback, NULL);

或這個:

StTrg_SetTransferEndCallback(cameraHandle, this->TransferEndCallback, NULL)

Visual Studio 2013說:

錯誤C3867:'MyNamespace :: MyClass :: TransferEndCallback':函數調用缺少參數列表; 使用'&MyNamespace :: MyClass :: TransferEndCallback'創建指向成員的指針

所以我按照建議使用它:

StTrg_SetTransferEndCallback(cameraHandle, &MyNamespace::MyClass::TransferEndCallback, NULL)

而且我收到此錯誤消息:

錯誤C2664:'BOOL StTrg_SetTransferEndCallback(HANDLE,funcTransferEndCallback,PVOID)':無法將參數2從'void(__stdcall MyNamespace :: MyClass :: *)(HANDLE,DWORD,DWORD,DWORD,DWORD,WORD,PBYTE,PVOID)'轉換為' funcTransferEndCallback'沒有可以進行此轉換的上下文

那么,是否可以將成員方法作為函數傳遞呢? 這是std::bind嗎?

該接口需要一個function回調。 C++ ,這意味着non-member函數或static函數。 這是因為這兩種類型的函數都被調用,而無需類對象實例 類的成員函數以不同的方式調用,並且需要類對象的實例。

如果需要更多說明,其他人可以詳細說明如何調用成員函數。

通常模式是通過實例的指針thisPVOID pvContext參數,然后使用它的回調中調用的成員函數。

public class Camera
{
// ...
void ThisTransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw);
static void __stdcall TransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext);
};

將回調設置為

StTrg_SetTransferEndCallback(cameraHandle, TransferEndCallback, this);

然后編寫靜態回調以將其分派給成員函數

void __stdcall Camera::TransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext)
{
    ((Camera *)pvContext)->ThisTransferEndCallback(hCamera, dwFrameNo, dwWidth, dwHeight, wColorArray, pbyteRaw);
}

以上不包括錯誤檢查等。

StTrg_SetTransferEndCallback(cameraHandle, &MyNamespace::MyClass::TransferEndCallback, NULL)

那是行不通的,因為沒有對象可以調用該方法。 正如Anon Mail所建議的那樣,靜態函數是實現此目的的最佳方法。 但是,您表示無法執行此操作。

我的建議是將您的類重構為單例並添加靜態前向函數。 例:

public class Camera
{
public:
static *Camera the()
{
  if (!singleton)
    singleton = new Camera;
  return singleton;
}
void destroy() { delete singleton; singleton = nullptr; }
 .....
private:
static void TransferEndCallbackForward(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext)
{
  assert(singleton != nullptr); // Implement your own error handling here
  singleton->TransferEndCallback(hCamera, dwFrameNo, dwWidth, dwHeight, wColorArray, pbyteRaw, pvContext);
}
void __stdcall TransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext);
static Camera *singleton = nullptr;
};

希望對您有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM