windows - ESP 的值未正确保存....和 ​​C/C++ 调用约定

标签 windows calling-convention thunk cdecl stack-pointer

我正在使用 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

最佳答案

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

关于windows - ESP 的值未正确保存....和 ​​C/C++ 调用约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8696436/

相关文章:

c++ - 从 C++ 调用 WDF 驱动程序

haskell - thunk 使用多少内存?

mysql - 从 Node 、mysql、koa中的thunk获取数据

c++ - 复合日期类型的调用约定

c# - C# 中非托管 DLL 的调用约定

assembly - ARM 调用约定是否允许函数不将 LR 存储到堆栈?

javascript - 如何将参数从组件传递到 redux 操作

java - 如何在 Windows 10 环境中从 Java 运行在 Ubuntu 上用 Bash 编写的 shell 脚本?

windows - $$PWD 不再适用于 Qt Creator 2.6

c - C语言中的软件中断?