2

我正在使用 OpenCV 库、Boost 库和我从这个LINK下载的一段代码编写一个应用程序。我已经在与 Thunk32 相同的解决方案下创建了一个项目,并且我有以下文件:

主项目.cpp

#include "stdafx.h"

int main( int argc, char** argv )
{
    IplImage *img = cvLoadImage( "C:/Users/Nicolas/Documents/Visual Studio 2010/Projects/OpenCV_HelloWorld/Debug/gorilla.jpg" );
    Window::WindowType1 *win = new Window::WindowType1("Something");
    cvNamedWindow( "window", CV_WINDOW_AUTOSIZE );
    cvShowImage( "window", img );
    cvSetMouseCallback( "oonga", (CvMouseCallback)win->simpleCallbackThunk.getCallback(), NULL );  

    while( true )
    {
        int c = waitKey( 10 );

        if( ( char )c == 27 )
        { break; }
    }
    return 0;
}

窗口.h

class Window {

public:
    Window();
    virtual ~Window();

    //virtual void mouseHandler( int event, int x, int y, int flags, void *param );

private:
    void assignMouseHandler( CvMouseCallback mouseHandler );

    class WindowWithCropMaxSquare;
    class WindowWithCropSelection;
    class WindowWithoutCrop;

public:
    typedef WindowWithCropMaxSquare WindowType1;
    typedef WindowWithCropSelection WindowType2;
    typedef WindowWithoutCrop WindowType3;

protected:
    
};

class Window::WindowWithCropMaxSquare : public Window {

public:
    indev::Thunk32<WindowType1, void _cdecl ( int, int, int, int, void* )> simpleCallbackThunk;

    WindowWithCropMaxSquare( char* name );
    ~WindowWithCropMaxSquare();

    void _cdecl mouseHandler( int event, int x, int y, int flags, void *param );

private:

protected:
    
};

Window.cpp

#include "stdafx.h"

Window::Window()
{

}

Window::~Window()
{

}

void Window::assignMouseHandler( CvMouseCallback mouseHandler )
{

}

Window::WindowWithCropMaxSquare::WindowWithCropMaxSquare( char* name )
{
    simpleCallbackThunk.initializeThunk(this, &Window::WindowWithCropMaxSquare::mouseHandler); // May throw std::exception
}

Window::WindowWithCropMaxSquare::~WindowWithCropMaxSquare()
{

}

void _cdecl Window::WindowWithCropMaxSquare::mouseHandler( int event, int x, int y, int flags, void *param )
{
    printf("entered mousehandler");
}

现在,当我运行它时,如果我不在窗口内移动鼠标,没关系,回调已成功传递给 cvSetMouseCallback 函数。cvSetMouseCallback 函数有三个参数 1. 窗口名称, 2. CvMouseCallback 和 NULL 字符。CvMouseCallback 定义为

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

而 CV_CDECL 只是 _cdecl 调用约定的重​​新定义。

#define CV_CDECL __cdecl

现在,我的 mouseHandler 函数是一个类成员函数,我假设它符合 _thiscall 调用约定。

我的问题是,当我将鼠标放在窗口上时,如果它至少成功进入该方法一次,为什么会出现以下错误?我猜我的鼠标在窗口内移动的第二个瞬间就会发生变化。任何人都可以帮助我吗?

这是我正在做的图像:

带有错误和结果的图像

4

1 回答 1

1

该 thunk 代码使用__stdcall约定,而不是__cdecl. 在这种情况下,由于cvSetMouseCallback需要将void*其传递给回调,因此我建议您使用静态回调函数并使用此数据指针来传递this指针。然后,您可以将您的逻辑放在这个静态函数中,或者只使用传入的指针调用回调的实例版本。

class Window {
public:
    void _cdecl staticMouseHandler( int event, int x, int y, int flags, void *param ) {
        ((MouseHandler*)param)->mouseHandler(event, x, y, flags, NULL);
    }
// ...
}

// ...

cvSetMouseCallback( "oonga", &Window::staticMouseHandler, win );  
于 2012-01-02T00:17:00.130 回答