Значение ESP не было сохранено должным образом .... и соглашения о вызовах C / C ++ - PullRequest
2 голосов
/ 02 января 2012

Я пишу приложение, используя библиотеки OpenCV, библиотеки Boost и пакет кода, который я скачал с этой LINK .Я создал проект под тем же решением с Thunk32, и у меня есть следующие файлы:

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

Window.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.

У меня такой вопрос: почему я получаю следующую ошибку, только когда кладу мышь в окно, если ей удалось хотя бы раз войти в метод?Я полагаю, что во второй момент моя мышь двигается в ветровом режимеМожет кто-нибудь помочь мне, пожалуйста?

Вот изображение с тем, что я делаю:

Image with error and results

1 Ответ

1 голос
/ 02 января 2012

Этот код 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 );  
...