【问题标题】:The value of ESP was not properly saved.... and C/C++ calling conventionsESP 的值未正确保存....和 ​​C/C++ 调用约定
【发布时间】:2012-01-02 00:00:42
【问题描述】:

我正在使用 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 调用约定。

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

这是我正在做的图片:

【问题讨论】:

    标签: windows calling-convention thunk cdecl stack-pointer


    【解决方案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 );  
    

    【讨论】:

    • 你知道我该怎么做吗?
    • 你有的staticMouseHandler函数里面的MouseHandler,到底是什么?不知何故,它不起作用。
    • 静态函数调用该函数的非静态版本。
    猜你喜欢
    • 2013-07-03
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 2015-09-06
    • 2011-09-17
    • 1970-01-01
    • 2013-11-30
    相关资源
    最近更新 更多