函数指针和回调

时间:2011-11-12 22:41:25

标签: c++ function pointers callback

我正在使用Microsoft Visual Studio 2010和OpenCV 2.3.0库来编写用于图像处理的应用程序。

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

我的 Window.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函数的指针,以便它可以被另一个类使用?

2 个答案:

答案 0 :(得分:1)

我认为你需要在这里使用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函数。

答案 1 :(得分:1)

您的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);
}