Функциональные указатели и обратные вызовы - PullRequest
0 голосов
/ 13 ноября 2011

Я использую Microsoft Visual Studio 2010 и библиотеки OpenCV 2.3.0 для написания приложения для обработки изображений.

У меня есть фрагмент кода, который для меня ошибочен, и я не уверен, какпочини это.Я реализую приложение, в котором одновременно будет открыто 2 или 3 окна, и я хочу, чтобы каждому из них была назначена отдельная функция CvMouseCallback .Я хочу, чтобы все эти CvMouseCallback функции находились в другом классе вместе с другой функцией, которая возвращает указатель на одну из этих функций в соответствии с тем, что выбрал пользователь.

My 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 file

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

Последний бит информации, который может вам понадобиться, - это определение CvMouseCallback из OpenCVбиблиотека, которая

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

Теперь возникает вопрос: когда я возвращаю обратный вызов из последней функции в MouseHandler.cpp, он подчеркивается ошибкой:

Ошибка:тип возвращаемого значения не соответствует типу функции.

Я знаю, что он говорит о том, что я пытаюсь навязать этой функции возврат чего-то, что не похоже на объект, который он запрашивает.Тем не менее, это просто функция, и если бы я мог сделать это в основном классе, все было бы в порядке.Моя проблема в том, как selectHandler может вернуть указатель на функцию selectROI, чтобы она могла использоваться другим классом?

Ответы [ 2 ]

1 голос
/ 13 ноября 2011

Ваш метод 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);
}
1 голос
/ 13 ноября 2011

Я думаю, что вам нужно использовать функцию 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...