GLFW.NET注册输入回调遇NullReferenceException问题求助
GLFW.NET 输入回调空引用错误及类型转换问题修复
问题根源
1. 空引用异常(NullReferenceException)
在Init()方法中,你分配内存存储WindowData并将指针传给GLFW后,立刻释放了这块内存。GLFW仅保存指针地址,回调触发时指针指向的内存已被回收,此时通过Marshal.PtrToStructure获取的WindowData是无效数据,EventCallback字段为null,调用时必然抛出空引用异常。
2. nint转GLFW.Window类型错误
GLFW.NET中GLFW.Window可直接通过IntPtr构造,无需强制转换,直接使用new GLFW.Window(window)即可解决CS1503错误。
修复步骤
1. 保留用户数据指针至窗口销毁
- 在类中添加成员变量保存用户数据指针:
private IntPtr m_WindowUserDataPtr;
- 修改
Init()方法,移除即时释放内存的代码:
// 替换原内存分配与释放逻辑 m_WindowUserDataPtr = Marshal.AllocHGlobal(Marshal.SizeOf(m_Data)); Marshal.StructureToPtr(m_Data, m_WindowUserDataPtr, false); Glfw.SetWindowUserPointer(m_window, m_WindowUserDataPtr); // 移除原代码中的Marshal.FreeHGlobal(dataPtr);
- 在
Shutdown()方法中先释放内存再销毁窗口:
public void Shutdown() { if (m_WindowUserDataPtr != IntPtr.Zero) { Marshal.FreeHGlobal(m_WindowUserDataPtr); m_WindowUserDataPtr = IntPtr.Zero; } Glfw.DestroyWindow(m_window); }
2. 同步回调中修改的WindowData
回调中修改WindowData的字段后,需将数据写回用户指针指向的内存,否则类成员m_Data不会同步更新:
// 以窗口大小回调为例,其他回调同理修改 Glfw.SetWindowSizeCallback(m_window, (window, width, height) => { IntPtr userPtr = Glfw.GetWindowUserPointer(window); WindowData data = Marshal.PtrToStructure<WindowData>(userPtr); WindowResizeEvent m_event = new WindowResizeEvent((uint)width, (uint)height); data.Width = (uint)width; data.Height = (uint)height; // 将修改后的数据写回内存 Marshal.StructureToPtr(data, userPtr, false); // 空值判断避免未注册回调时崩溃 data.EventCallback?.Invoke(m_event); });
3. 修复回调中窗口类型转换
若需在回调中使用GLFW.Window对象,直接通过IntPtr构造:
GLFW.Window glfwWindow = new GLFW.Window(window); // 后续可调用GLFW方法,如Glfw.GetWindowSize(glfwWindow)
4. 同步外部设置的回调
修改SetEventCallback方法,确保外部设置回调时,用户指针内存中的数据同步更新:
public override void SetEventCallback(in EventCallbackFn callback) { m_Data.EventCallback = callback; if (m_WindowUserDataPtr != IntPtr.Zero) { Marshal.StructureToPtr(m_Data, m_WindowUserDataPtr, false); } }
内容的提问来源于stack exchange,提问作者Bobi
相关产品推荐
相关产品推荐

