While making an OpenGL toolkit using GLFW and Cython I stumbled upon a very, very weird issue. I created the following file pxd file (quite large, so I gisted it):
https://gist.github.com/1441970
Next I have this wrapping code (extremely simplified to show the core of the problem).
pygrafix.window module:
from pygrafix.c_headers.glfw cimport * # this is the pxd file
glfwInit()
_window = None
cdef void _mouse_scroll_callback_handler(int pos):
if _window._mouse_scroll_callback:
_window._mouse_scroll_callback(_window, pos)
cdef class Window:
cdef public object _mouse_scroll_callback
def __cinit__(self):
global _window
self._mouse_scroll_callback = None
_window = self
def __init__(self, int width = 0, int height = 0):
glfwOpenWindow(width, height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW)
glfwSetMouseWheelCallback(<GLFWmousewheelfun> &_mouse_scroll_callback_handler)
print("TEST LOCATION ONE")
def is_open(self):
return glfwGetWindowParam(GLFW_OPENED)
def flip(self):
glfwSwapBuffers()
def set_mouse_scroll_callback(self, func):
self._mouse_scroll_callback = func
And this main file:
from pygrafix import window
window = window.Window(800, 600)
print("TEST LOCATION TWO")
def on_scroll(window, pos):
print(pos)
window.set_mouse_scroll_callback(on_scroll)
while window.is_open():
window.flip()
And finally I compile it like this:
cython.py -o pygrafix/window.cy.c pygrafix/window.pyx
gcc -O3 -shared -DGLFW_DLL -IC:\Python27\include pygrafix/window.cy.c -o pygrafix/window.pyd -LC:\Python27\libs -lpython27 -lgfwldll
But it crashes (windows says there was an error in the program). When I comment out the call to glfwSetMouseWheelCallback it doesn’t crash.
The strange thing is, if I compile with -O0 it doesn’t crash and works as it should! I am completely baffled by this. I checked the C code that cython outputs, and it looks ok.
_mouse_scroll_callback_handler is of the type void (*)(int), and the pointer to it gets passed nicely into glfw.
Other oddities:
- This only happens with
glfwSetMouseWheelCallback(or at least to me), not with glwSetMousePosCallback for example. - If I pass NULL to
glfwSetMouseWheelCallback, there is no problem. - Even if there is a crash, TEST LOCATION ONE still gets printed, but TEST LOCATION TWO doesn’t.
- It also works if I compile with -O3 -pg
What could possibly be the cause of this, and what would be the correct fix (without having to compile at -O0)?
Other trivia:
I’m using Windows 7 64 bit, GLFW 2.7.2, Cython 0.15.1, GCC 4.6.1 under MinGW and CPython 2.7.2.
I finally found the solution. The problem was that I didn’t add
__stdcallin Cython to the callback functions, nor did I know it supported this.