使用Marshal::GetFunctionPointerForDelegate并从非托管代码调用回调会导致退出应用程序



我使用Visual Studio 2008与。net Framework 3.5和制作c++/CLI/。NET Forms应用;游戏的编辑器。除了编辑器之外,所有的游戏代码都是纯c++编写的。我要到一个点,我需要在窗体代码回调从非托管代码调用。

我使用GetFunctionPointerForDelegate。

首先,我有这些在我的表单类:

public: delegate void ADelegate(Int32, float, float, float, Int32);
public: static ADelegate^ delegateInstance;

然后在Form构造函数中设置回调:

        // Set up World Objects callback
        typedef void (__stdcall *WorldLocationUpdateCallback)(Int32, float, float, float, Int32);
        WorldLocationUpdateCallback _callback;
        // Create an instance of a delegate, using GetFunctionPointerForDelegate
        delegateInstance = gcnew ADelegate( this, &MainForm::InitWorldObjectPane );
        // Convert the delegate to a pointer
        IntPtr anIntPtr = Marshal::GetFunctionPointerForDelegate( delegateInstance );
        // Cast the pointer into a function pointer
        _callback = static_cast<WorldLocationUpdateCallback>(anIntPtr.ToPointer());
        CEditorUI::UI()->setWorldLocationUpdateCallback( (void*)_callback );

所以我存储指针并在非托管代码中,在我的应用程序初始化的早期从不同的线程调用回调:

    // Set up World Object pane in editor to use this map/maptile/etc
    {
        typedef void (*WorldLocCallback)(int, float, float, float, int);
        void* _callback = CEditorUI::UI()->getWorldLocationUpdateCallback();
        int _mapId = charGfxObj->getMapId();
        float _posX = charGfxObj->getPos().x;
        float _posY = charGfxObj->getPos().y;
        float _posZ = charGfxObj->getPos().z;
        int _tileRadius = TILE_RADIUS;
        ((WorldLocCallback)(_callback))( _mapId, _posX, _posY, _posZ, _tileRadius );
    }

在我的应用程序中,一切都工作得很完美,直到我关闭应用程序。它总是在调用线程中出现缓冲区溢出错误而死亡,调用堆栈相当无用:

editor.exe!__crt_debugger_hook()    Unknown
>editor.exe!__report_gsfailure()  Line 298 + 0x7 bytes  C
editor.exe!__CorExeMain@0()  + 0xe3 bytes   C++

这里的问题是,即使回调实际上什么都不做,它也会崩溃。要引起崩溃,我所要做的就是启用调用回调的最后一行代码。这条线路被关闭了,没有问题。请记住,崩溃只会在退出时发生,而不会在实际使用回调时发生。

有什么建议吗?

经过一整天的折腾和寻找其他相关的东西,我在某种程度上解决了这个问题,以防其他人有这个问题。

将委托声明移出类并使用:

装饰它
[UnmanagedFunctionPointerAttribute(CallingConvention::Cdecl)] 

…帮我解出来了。显然,cdecl的堆栈清除效果解决了溢出问题。

相关内容

最新更新