Reputation: 1706
I'm trying to create a right-click-popup-menu in a Python(v2.7) program using GLUT. I haven't found Python-specific documentation for doing this, so I used C++ documentation, which is usually almost similar.
Here's what I have:
if __name__=="__main__":
glutInit(sys.argv)
#...more initialization code...
createMenu()
init()
glutMainLoop()
And here are the functions that create the menu:
def createMenu():
menu = glutCreateMenu(processMenuEvents)
glutAddMenuEntry("One", 1)
glutAddMenuEntry("Two", 2)
glutAttachMenu(GLUT_RIGHT_BUTTON)
def processMenuEvents(option):
logging.debug("Menu pressed")
# not using 'option' right now
The menu gets displayed correctly, but when I click on an item, I get this error:
DEBUG:root:Menu pressed:
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 338, in 'converting callback result'
TypeError: an integer is required
Exception in <function processMenuEvents at 0x1760b90> ignored
Does python-opengl have a different way of doing this? What am I doing wrong here?
Thanks.
Upvotes: 2
Views: 2454
Reputation: 2582
This example helped me identify the requirement for specifying function parameter ctypes to solve the same problem. Found following the pyopengl glut
docs on glutAddMenuEntry(). Ctype data types for your function args are specified here.
This snippet shows an example of an f(int)->int
function, referenced via an object instance:
class Menu:
def select_menu(self, choice):
def _exit():
import sys
sys.exit(0)
{
1: _exit
}[choice]()
glutPostRedisplay()
return 0
def create_menu(self):
# --- Right-click Menu --------
from ctypes import c_int
import platform
#platform specific imports:
if (platform.system() == 'Windows'):
#Windows
from ctypes import WINFUNCTYPE
CMPFUNCRAW = WINFUNCTYPE(c_int, c_int)
# first is return type, then arg types.
else:
#Linux
from ctypes import CFUNCTYPE
CMPFUNCRAW = CFUNCTYPE(c_int, c_int)
# first is return type, then arg types.
myfunc = CMPFUNCRAW(self.select_menu)
selection_menu = glutCreateMenu( myfunc )
glutAddMenuEntry("Quit", 1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
# ---------------------------------
Upvotes: 0
Reputation: 11
Unfortunately, the way that PyOpenGL has defined the callback function, it expects an int as the return type, not void. Below is an updated version of your CreateMenu callback function that should work.
def CreateMenu():
menu = glutCreateMenu(processMenuEvents)
glutAddMenuEntry("One", 1)
glutAddMenuEntry("Two", 2)
glutAttachMenu(GLUT_RIGHT_BUTTON)
# Add the following line to fix your code
return 0
Upvotes: 1
Reputation: 476
Specifying callback functions via ctypes in Python doesn't quite work like you are expecting. You should use CFUNCTYPE to create the callback function and use the resulting variable as the parameter to glutCreateMenu.
You will find more details on ctypes and callback functions here: http://docs.python.org/release/2.5.2/lib/ctypes-callback-functions.html
Upvotes: 0