我正在使用Visual Studio 2008和.NET Framework 3.5并制作C ++ / CLI / .NET Forms应用程序;一个游戏的编辑。除编辑器之外的所有游戏代码都是纯C ++。我需要从非托管代码中调用Forms代码中的回调。
我正在使用GetFunctionPointerForDelegate。
首先我在Form类中有这些:
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++
这里的踢球者即使回调几乎没有任何内容也崩溃了。导致崩溃的所有方法是启用调用回调的最后一行代码。禁用该行,没有问题。请记住,崩溃只在退出时发生,而不是在实际使用回调时发生。
有任何建议要尝试吗?
答案 0 :(得分:5)
经过一整天的讨论并寻找其他相关的事情,我有点解决了这个问题,以防其他人有这个问题。
将委托声明移到课堂外并用以下内容进行装饰:
[UnmanagedFunctionPointerAttribute(CallingConvention::Cdecl)]
......为我解决了。显然,cdecl的堆栈清除效果可以解决溢出问题。