函数指针和回调函数

Function pointers and callbacks

本文关键字:函数 回调 指针      更新时间:2023-10-16

我使用Microsoft Visual Studio 2010和OpenCV 2.3.0库编写了一个图像处理应用程序。

我有一段对我来说是错误的代码,我不知道如何修复它。我正在实现一个应用程序,其中将有2或3个窗口同时打开,我希望它们中的每一个都被分配一个不同的CvMouseCallback函数。我希望所有这些CvMouseCallback函数与另一个函数一起在不同的类中,该函数根据用户选择的内容返回指向其中一个函数的指针。

My windows .h包含这段代码。

class Window
{
public:
   ... // constructors and destructors
   void setMouseHandler( CvMouseCallback mouseHandler );
private:
   ... // other stuff
};

Window.cpp

#include "stdafx.h"
void Window::setMouseHandler( CvMouseCallback mouseHandler )
{
    cvSetMouseCallback( win, mouseHandler, NULL );
}
现在,MouseHandler.h文件
class MouseHandler
{
public:
   ...
   CvMouseCallback selectHandler( int option );
   void __cdecl selectROI( int event, int x, int y, int flags, void *param );
private:
   Image *in;
   Window *win;
   void ( CV_CDECL MouseHandler::*callback )( int event, int x, int y, int flags, void *param );
};

最后,在MouseHandler.cpp中包含

void __cdecl MouseHandler::selectROI( int event, int x, int y, int flags, void *param )
{
   //do something
}
CvMouseCallback MouseHandler::selectHandler( int option )
{
   callback = (MouseHandler::selectROI);
   return callback;
}

您可能需要的最后一点信息是来自OpenCV库的CvMouseCallback的定义

typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);

现在,问题是:当我从MouseHandler.cpp中的最后一个函数返回回调时,它下划线显示错误:

错误:返回值类型与函数类型不匹配

我知道它说的是我试图强加给那个函数返回的东西看起来不像它正在请求的对象。然而,它只是一个函数,如果我能在主类中做到这一点,那就没问题了。我的问题是如何selectHandler返回一个指向selectROI函数的指针,以便它可以被另一个类使用?

我认为您需要在这里使用static函数:

static void __cdecl selectROI( int event, int x, int y, int flags, void *param );

void ( CV_CDECL *callback )( int event, int x, int y, int flags, void *param );
相应的

问题是这个定义:

typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);

不是类成员函数,而您的函数是类MouseHandler的成员,这意味着它有不同的签名和不同的参数列表(以适应this)。使用static类成员函数为您解决了这个问题。

您必须弄清楚如何将对象上下文数据传递给static函数。

您的selectROI()方法,因为它不是静态的,需要一个隐式的this参数作为它的第一个参数。如果你尝试使它静态,你将有一个更好的机会让它工作,虽然实际上,如果你是传递给一个C API,你技术上需要传递一个extern "C"函数指针,一切都是完全正确和可移植的。这可能是一个简单的转发函数,像这样:

extern "C" void selectROI( int event, int x, int y, int flags, void *param );

然后,如果你想让你的c++类方法不是静态的(所以它可以访问类成员变量),你只需要传递一个指向MouseHandler对象的指针作为cvSetMouseCallback()的第三个参数,然后你将在你的回调中接收到相同的参数,然后看起来像这样:

extern "C" void selectROI( int event, int x, int y, int flags, void *param )
{
    static_cast<MouseHandler*>(param)->selectROI( event, x, y, flags);
}