繁体   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