I have a problem with the glfwSetCharCallback function. Whenever I call it, glfwPollEvents throws an AccessViolationException saying: "Attempted to read or write protected memory. This often indicates that other memory is corrupt."
I created a very simple shell to demonstrate the problem:
using System; using System.Runtime.InteropServices; using System.Security; namespace Test { public delegate void GlfwCharCallback(GlfwWindow window, Char character); [StructLayout(LayoutKind.Explicit)] public struct GlfwMonitor { private GlfwMonitor(IntPtr ptr) { _nativePtr = ptr; } [FieldOffset(0)] private readonly IntPtr _nativePtr; public static readonly GlfwMonitor Null = new GlfwMonitor(IntPtr.Zero); } [StructLayout(LayoutKind.Explicit)] public struct GlfwWindow { private GlfwWindow(IntPtr ptr) { _nativePtr = ptr; } [FieldOffset(0)] private readonly IntPtr _nativePtr; public static GlfwWindow Null = new GlfwWindow(IntPtr.Zero); } public class Wrap { [DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] private static extern Int32 glfwInit(); [DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] internal static extern GlfwWindow glfwCreateWindow(Int32 width, Int32 height, [MarshalAs(UnmanagedType.LPStr)] String title, GlfwMonitor monitor, GlfwWindow share); [DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] internal static extern void glfwSetCharCallback(GlfwWindow window, GlfwCharCallback callback); [DllImport("GLFW3", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] internal static extern void glfwPollEvents(); public static Boolean Init() { return glfwInit() == 1; } public static GlfwWindow CreateWindow(Int32 width, Int32 height, String title, GlfwMonitor monitor, GlfwWindow share) { return glfwCreateWindow(width, height, title, monitor, share); } public static void SetCharCallback(GlfwWindow window, GlfwCharCallback callback) { glfwSetCharCallback(window, callback); } public static void PollEvents() { glfwPollEvents(); } } }
And I call it as if GLFW:
using System; namespace Test { class Program { static void Main() { Wrap.Init(); var window = Wrap.CreateWindow(800, 600, "None", GlfwMonitor.Null, GlfwWindow.Null); Wrap.SetCharCallback(window, (glfwWindow, character) => Console.WriteLine(character)); while(true) { Wrap.PollEvents(); } } } }
The character prints to the console and I get an AccessViolationException.
What am I doing wrong? All DllImports define a CDecl calling convention (I tried others on PollEvents and SetCharCallback), I tried all CharSets in the SetCharCallback function and nothing worked.
Can anyone help me out?
Edit:
Here is the GLFW3 DLL that I am using: http://www.mediafire.com/?n4uc2bdiwdzddda
Edit 2:
Using the latest lib-msvc110 DLL created by glfwSetCharCallback. glfwSetKeyCallback and glfwSetCursorPosCallback do not work and continue to throw an AccessViolationException. I will try to understand what makes CharCallback so special, but to be honest, I went through the GLFW source code through and through all the functions it seems to do its job the same way. Maybe I missed something.
Edit 3:
I tried everything: cdecl, stdcall, all encodings, all versions of dll, all combinations of arguments, etc. I made sure callbacks are not deleted by storing a reference to them. I also tried to purposefully collapse the application without leaving any arguments to glfwSetCharCallback (which currently works), and I failed. This makes me think that the arguments themselves are not relevant to the application.
What really makes me think that the error is related to GLFW is that if I compile with x86-64 dll, everything works fine. It's a little strange to use cdecl on x86-64 because MSDN specifically states that the only call is fastcall.