Python pyglet.graphics:ctypes数组创建中的索引器

Python pyglet.graphics:ctypes数组创建中的索引器,python,debugging,opengl,ctypes,pyglet,Python,Debugging,Opengl,Ctypes,Pyglet,我正在和pyglet一起开发一个小游戏。当然,其中一个中心是画彩色的长方形天使。我最初是通过在内存中创建图像和blit()ing来实现的,效果很好。在注意到这是多么丑陋、迂回和低效(是的,我分析了-ColorRect.draw()花费了大量的时间,通过这次更改效率提高了10倍)之后,我开始通过pyglet.graphics.Batch(我从一个示例中逐字复制了大部分代码)创建顶点列表。从那以后,我在一些低级OpenGL代码中遇到了一个奇怪的异常,我无法找到原因或可靠地复制它 这和游戏性事件没有明

我正在和pyglet一起开发一个小游戏。当然,其中一个中心是画彩色的长方形天使。我最初是通过在内存中创建图像和
blit()
ing来实现的,效果很好。在注意到这是多么丑陋、迂回和低效(是的,我分析了-
ColorRect.draw()
花费了大量的时间,通过这次更改效率提高了10倍)之后,我开始通过
pyglet.graphics.Batch
(我从一个示例中逐字复制了大部分代码)创建顶点列表。从那以后,我在一些低级OpenGL代码中遇到了一个奇怪的异常,我无法找到原因或可靠地复制它

这和游戏性事件没有明显的关系——比如,之前没有什么特别的事情发生,或者我经常错过它。由于错误发生在事件循环的深处,我无法轻松跟踪是哪个位置更新导致了错误。老实说,我被难住了。因此,我将把我所发现的抛诸脑后,并希望找到某种通灵者

我已经用Python3.2.2在Windows7 32位上试用过了(我可能很快会在Ubuntu 11.10上试用),pyglet版本为043180b64260(从Goggle代码中提取,并从源代码中构建,1.1.4版本更难安装,因为它不会自动运行2to3,尽管它似乎同样支持py3k)。下一步我可能会更新到最新的mercurial版本,但这只是几个提交,更改似乎完全无关

完整的回溯(出于原则,对某些路径进行了审查,但请注意,这是在其自己的virtualenv中):

回溯(最近一次呼叫最后一次):
文件“”,第152行,在
main()
文件“”,第148行,主
运行()
文件“”,第125行,正在运行
pyglet.app.run()文件
文件“\Lib\site packages\pyglet\app\\uuuu init\uuuuu.py”,第123行,正在运行
event_loop.run()
文件“\Lib\site packages\pyglet\app\base.py”,第135行,正在运行
自我评估
文件“\Lib\site packages\pyglet\app\base.py”,第164行,在
超时=self.idle()
文件“\Lib\site packages\pyglet\app\base.py”,第278行,处于空闲状态
窗口。将_切换到()
文件“\Lib\site packages\pyglet\window\win32\\uuuu init\uuuuu.py”,第305行,在switch\u to中
self.context.set_current()
文件“\Lib\site packages\pyglet\gl\win32.py”,第213行,当前设置
super(Win32Context,self).set_current()
文件“\Lib\site packages\pyglet\gl\base.py”,第320行,当前设置
缓冲区=(gl.GLuint*len(缓冲区))(*缓冲区)
索引器:索引无效
使用验尸报告运行(在FPS从60下降到7时,在代码中积极地逐步执行,直到它碰巧不可行)
pdb
显示:

  • buffers
    是一个整数列表;我不知道它们代表什么,也不知道它们来自哪里,但它们是从一个名为
    self.object\u space.\u detered\u textures
    (其中
    self
    是一个窗口对象)的列表中提取出来的。关联的注释表示此代码块释放了计划删除的纹理。我不认为我在任何地方都明确使用纹理,但谁知道pyglet在引擎盖下做了什么。我假设这些整数就是要销毁的纹理的ID或某些东西
  • gl.GLuint
    ctypes.c_ulong
    的别名;因此,
    (gl.GLuint*len(buffers))(*buffers)
    创建一个长度和内容相同的
    ulong
    数组
  • 我可以在
    pdb
    提示符下计算相同的表达式,而不会出现错误或数据损坏
使用ctypes的独立实验(在virtualenv之外,不导入pyglet)表明,如果给数组构造函数提供太多参数,则会引发
索引器
。这毫无意义,实验和逻辑都表明长度和参数计数必须始终匹配

  • 是否还有其他可能发生此异常的情况?这可能是pyglet的错误,还是我误用了库并错过了相关警告
  • 创建和维护顶点列表的代码在调试时是否有用?可能是出了什么问题。我已经开始关注它了,但由于我对
    pyglet.graphics
    几乎没有经验,所以它的用途有限。如果您想查看
    ColorRect
    代码,请留下评论
  • 还有其他想法吗?是什么原因造成的

  • 要提供一个真正相关的答案有点困难,因为没有提供代码,但从错误输出中我可以看到

    buffers = (gl.GLuint * len(buffers))(*buffers)
    
    因此,如果我理解正确的话,就是将GLuint的大小(4字节)乘以缓冲区的实际长度(如果初始化)。也许这就是你的索引无效的原因,因为它太高了

    通常这是可以的,因为缓冲区是以字节为单位的,但是你说它是一个整数列表


    希望有帮助

    您能让舒尔不使用多线程吗?如果多个线程处于活动状态,则可能会导致
    base.py中出现问题。当在运行单个GLuint构造函数填充数组之前分配数组时,另一个线程可能会更改
    缓冲区。因此
    len(buffer)
    (*buffers)
    长度不匹配。@drous歪理邪说!我没有在任何地方使用线程,我怀疑pyglet是否会尝试并行运行。但是我会检查sys.modules中的
    “U线程”
    @dronus是否忘记了
    “U线程”
    ,它显然总是导入的(我检查了一个新的解释器会话)<另一方面,代码>线程化
    在我的代码中导入,但不在解释器会话中导入<代码>线程。枚举
    仅给出
    []
    。我将添加一个断言,说明这始终是正确的,并调查是谁导入了
    线程
    @dronus似乎
    日志
    导入
    线程
    pyglet.app.base
    也可以,但显然它只使用
    线程化.Event
    队列
    (这反过来会导入
    虚拟线程化
    
    buffers = (gl.GLuint * len(buffers))(*buffers)