PyOpenGL glReadPixels causes ctypes Argument error after final POINTER creation

330 Views Asked by At

I'm having a strange issue with pyopengl and its imports, below is a small test program cut out of a much larger one, but it is enough to show the problem. You need PyOpenGL installed, and if you run it as it is it shows a blank window, and if you click and drag it prints out some 0s. If you uncomment the line HANDLE.final = True below, then it stops working, see the traceback below.

from OpenGL.GL import *
from OpenGL.GLUT import *
from ctypes import POINTER
import sys

HANDLE = POINTER(None)
#HANDLE.final = True

def display():
    glutSwapBuffers()

glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(400,400)
glutCreateWindow("GLUT Window")

glutDisplayFunc(display)

def readPx(x,y):
    data_all = glReadPixels(x, y, 1, 1, GL_RGB, GL_BYTE)
    print data_all

glutMotionFunc(readPx)

glutMainLoop()

With that line uncommented it does this:

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\OpenGL\GLUT\special.py", line 130, in safeCall
    return function( *args, **named )
  File "C:\Users\Robin\dev\ogl_bug\ogl_bug.py", line 19, in readPx
    data_all = glReadPixels(x, y, 1, 1, GL_RGB, GL_BYTE)
  File "C:\Python27\lib\site-packages\OpenGL\GL\images.py", line 371, in glReadPixels
    imageData
  File "C:\Python27\lib\site-packages\OpenGL\platform\baseplatform.py", line 402, in __call__
    return self( *args, **named )
ArgumentError: argument 7: <type 'exceptions.TypeError'>: wrong type
GLUT Motion callback <function readPx at 0x02CC5830> with (238, 190),{} failed: returning None argument 7: <type 'exceptions.TypeError'>: wrong type

In my bigger program, this HANDLE code is buried 5 or 6 imports deep when trying to import OpenGL.raw.WGL._types, which is imported by any WGL Opengl extension but this is the smallest fragment that still causes the error.

I don't understand why the presence of this line is having an effect on a seemingly unrelated gl call - how can I use the load this extension without breaking other parts of PyOpenGL?

1

There are 1 best solutions below

0
On

I found the reason - POINTER(None) gives back ctypes.c_void_p, which is a singleton, and means the .final attribute is visible gloablly after this import, presumable upsetting some type checking mechanism later.

It is fixed in the github version of PyopenGL. This is the commit:

https://github.com/mcfletch/pyopengl/commit/f087200406a37fc4b99eaad701d18bc64ded2d71

You can fix it in the current release of PyOpenGL by importing this small module before any OpenGL extensions:

import OpenGL.raw.WGL._types as t
from ctypes import _SimpleCData, _check_size

delattr(t.HANDLE, "final")

class HANDLE(_SimpleCData):
    _type_ = "P"

_check_size(HANDLE)

HANDLE.final = True

t.HANDLE = HANDLE
t.HGLRC = HANDLE
t.HDC = HANDLE

t.HPBUFFERARB = HANDLE
t.HPBUFFEREXT = HANDLE

This imports the PyOpenGL module that causes the problem, undoes the damage to c_void_p, then reassigns the HANDLE variable and its aliases to the _SimpleCData solution from the github link above.