使用 c++ class 方法作为函数回调
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);
我不想创建回调函数,而是使用 class 中的方法。我在我的 classe 的构造函数中调用这个 StTrg_SetTransferEndCallback()
,所以我可以初始化相机并传递我的 classe 的方法来捕获每个新帧并处理它。
我的方法在我的 class.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 年说:
error C3867: 'MyNamespace::MyClass::TransferEndCallback': function call missing argument list; use '&MyNamespace::MyClass::TransferEndCallback' to create a pointer to member
所以我按照建议使用它:
StTrg_SetTransferEndCallback(cameraHandle, &MyNamespace::MyClass::TransferEndCallback, NULL)
我收到了这条错误信息:
error C2664: 'BOOL StTrg_SetTransferEndCallback(HANDLE,funcTransferEndCallback,PVOID)' : cannot convert argument 2 from 'void (__stdcall MyNamespace::MyClass::* )(HANDLE,DWORD,DWORD,DWORD,WORD,PBYTE,PVOID)' to 'funcTransferEndCallback' There is no context in which this conversion is possible
那么,是否可以将成员方法作为函数传递?这是 std::bind
的情况吗?
StTrg_SetTransferEndCallback(cameraHandle, &MyNamespace::MyClass::TransferEndCallback, NULL)
那是行不通的,因为没有对象可以调用该方法。
正如 Anon Mail 建议的那样,静态函数是最好的方法。
但是,你说你不能那样做。
我的建议是将您的 class 重构为单例并添加静态前向函数。
示例:
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;
};
希望对你有所帮助
接口需要function
回调。在 C++
中,这意味着 non-member
函数或 static
函数。这是因为调用这两种类型的函数时不需要class 对象 的实例。 class 的成员函数以不同方式调用,需要 class 对象的实例。
如果您需要更多解释,其他人可以详细说明在幕后如何调用成员函数。
通常的模式是将实例指针 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);
然后写静态回调派发给成员函数
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);
}
以上不包括错误检查等
我使用的相机 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);
我不想创建回调函数,而是使用 class 中的方法。我在我的 classe 的构造函数中调用这个 StTrg_SetTransferEndCallback()
,所以我可以初始化相机并传递我的 classe 的方法来捕获每个新帧并处理它。
我的方法在我的 class.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 年说:
error C3867: 'MyNamespace::MyClass::TransferEndCallback': function call missing argument list; use '&MyNamespace::MyClass::TransferEndCallback' to create a pointer to member
所以我按照建议使用它:
StTrg_SetTransferEndCallback(cameraHandle, &MyNamespace::MyClass::TransferEndCallback, NULL)
我收到了这条错误信息:
error C2664: 'BOOL StTrg_SetTransferEndCallback(HANDLE,funcTransferEndCallback,PVOID)' : cannot convert argument 2 from 'void (__stdcall MyNamespace::MyClass::* )(HANDLE,DWORD,DWORD,DWORD,WORD,PBYTE,PVOID)' to 'funcTransferEndCallback' There is no context in which this conversion is possible
那么,是否可以将成员方法作为函数传递?这是 std::bind
的情况吗?
StTrg_SetTransferEndCallback(cameraHandle, &MyNamespace::MyClass::TransferEndCallback, NULL)
那是行不通的,因为没有对象可以调用该方法。 正如 Anon Mail 建议的那样,静态函数是最好的方法。 但是,你说你不能那样做。
我的建议是将您的 class 重构为单例并添加静态前向函数。 示例:
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;
};
希望对你有所帮助
接口需要function
回调。在 C++
中,这意味着 non-member
函数或 static
函数。这是因为调用这两种类型的函数时不需要class 对象 的实例。 class 的成员函数以不同方式调用,需要 class 对象的实例。
如果您需要更多解释,其他人可以详细说明在幕后如何调用成员函数。
通常的模式是将实例指针 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);
然后写静态回调派发给成员函数
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);
}
以上不包括错误检查等