使用c ++类方法作为函数回调

时间:2015-12-04 17:55:13

标签: c++ function methods callback std

我正在使用相机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);

我不想创建回调函数,而是实际使用类中的方法。我在classe的构造函数中调用了这个StTrg_SetTransferEndCallback(),所以我可以初始化相机并传递我的classe方法来捕获每个新帧并处理它。

我的方法在我的班级.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)':无法从'void(__stdcall MyNamespace :: MyClass :: *)转换参数2(HANDLE,DWORD,DWORD,DWORD,WORD,PBYTE,PVOID) 'to'funcTransferEndCallback'没有可以进行此转换的上下文

那么,是否可以将成员方法作为函数传递?这是std::bind的情况吗?

3 个答案:

答案 0 :(得分:2)

界面需要function回调。在C++中,这意味着non-member函数或static函数。这是因为在不需要类对象的实例的情况下调用这两种类型的函数。类的成员函数的调用方式不同,需要一个类对象的实例。

如果您需要更多解释,其他人可以详细说明如何调用成员函数。

答案 1 :(得分:2)

常用模式是将实例指针import Darwin public class foo { private var boolTest : Bool? init() { boolTest = true } public func call() -> AnyObject? { if let bool = boolTest { return bool } else { return nil } } } foo().call() 传递给this参数,然后在回调中使用它来调用成员函数。

PVOID 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);

上述内容并未包含错误检查等。

答案 2 :(得分:1)

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;
};

我希望能帮助你。