好吧,我非常接近完成这个我可以品尝它.在过去几周左右的时间里,我一直在尝试创建一个Python扩展,以便通过Cython与用C++编写的库进行交互.在这里和一些朋友的帮助下,我已经设法获得了98%的感觉.唯一剩下的就是这个:我不能为我的生活找出如何将指向无符号短裤数组的指针变成python对象(最好是列表).
一点背景,我试图与设置回调函数的库的一部分接口,我已经成功完成了这个:
global callbackfunc
ctypedef unsigned short const_ushort "const uint16_t"
ctypedef void (*Function1)(const_ushort *data, unsigned width, unsigned height)
cdef extern from "lib.hpp":
void SetCallback(Function1)
cdef void cSetCallback(Function1 function):
SetCallback(function)
cdef void callcallback(const_ushort *data, unsigned width, unsigned height):
global callbackfunc
callbackfunc(data,width,height)
cSetCallback(callcallback)
def PySetCallback(callbackFunc):
global callbackfunc
callbackfunc = callbackFunc
Run Code Online (Sandbox Code Playgroud)
问题出现在函数"callcallback"中,我得到错误:"无法将'const_ushort*'转换为Python对象".我第一次尝试这个是创建一个新的python列表,并循环以将数组的每个元素放入python列表,如下所示:
datalist = []
for i in range(width*height):
datalist += data[i]
Run Code Online (Sandbox Code Playgroud)
遗憾的是,在编译的cython代码中,我试图将类型定义为"const const unsigned short",这显然是一个问题.
然后我尝试了这个:
datalist = []
for i in data:
datalist += i
Run Code Online (Sandbox Code Playgroud)
这让我"C数组迭代需要已知的结束索引".请注意,我对C/C++知之甚少,所以大部分内容对我来说都没有多大意义.
所以,无论如何,是否有任何有效的方法将这样的指针转换为python对象(最好比循环遍历数组更快,因为它通常约为57344项,这对时间非常敏感)
编辑:稍微澄清一下,正如我所提到的,我正在使用回调,并且调用它的库中的C++函数会发送一个指向"const uint_16"数组的指针,这就是我用这种方式定义const_ushort的原因,因为否则类型不统一.我无法以任何方式修改库.
Edit2 …
我一直在使用Cython尝试与用c ++编写的库进行交互.到目前为止,事情进展顺利,我可以有效地使用库中的MOST函数.我唯一的问题在于实现回调.该库有4个函数定义,看起来像这样:
typedef void (*Function1)(const uint16_t *data,
unsigned width, unsigned height);
void SetCallBack(Function1);
Run Code Online (Sandbox Code Playgroud)
所以为了实现它们,我想我会用cython做这样的事情:
ctypedef void (*Function1)(unsigned short *data,
unsigned width, unsigned height);
cdef extern from "lib.hpp":
void SetCallBack(Function1)
Run Code Online (Sandbox Code Playgroud)
然而,实际上编译正确,我不能为我的生活思考如何以回调可行的方式实际实现它.我首先尝试创建一个只调用它的函数,类似于你为任何其他函数执行它的方式,得出这个:
def PySetCallBack(Func):
SetCallBack(Func)
Run Code Online (Sandbox Code Playgroud)
但这给了我(可预测的)错误:
"无法将Python对象转换为'Function1'"
所以,是的,那就是我在的地方.如果有人有任何在Cython中设置回调的经验,我将非常感谢任何帮助.谢谢.
编辑:根据您的建议,我创建了一个带有cdef的中间函数,如下所示:
cdef void cSetCallBack(Function1 function):
SetCallBack(function)
Run Code Online (Sandbox Code Playgroud)
这似乎让我...更近了?至少现在得到一个不同的错误:
error: invalid conversion from ‘void (*)(short unsigned int*, unsigned int, unsigned int)’ to ‘void (*)(const uint16_t*, unsigned int, unsigned int)’
Run Code Online (Sandbox Code Playgroud)
现在,我可以说这些类型是相同的,所以我无法弄清楚发生了什么.
Edit2:通过声明一个新的typedef修复了这个问题:
ctypedef unsigned short uint16_t
Run Code Online (Sandbox Code Playgroud)
并使用它作为调用的参数,但显然实际上并没有更接近,但只是带我绕过一个侧轨,因为当试图调用该函数时,我得到相同的"无法将Python对象转换为'Function1' "再次出错.
所以,我几乎回到了我开始的地方.我现在唯一可以做的就是明确地将python对象作为交流函数进行投射,但是,说实话,我不知道如何去做.
编辑第三个:好吧,在解析你的答案之后我终于得到了它,它有效,所以万岁等等.我最终做的是创建这样的函数:
cdef void cSetCallback(Function1 function): …Run Code Online (Sandbox Code Playgroud) 我正在使用PyOpenGL开发一个项目,我正在尝试让OpenGL呈现一种启动画面.我决定的解决方案是绘制纹理2D矩形.不幸的是,似乎无论我做什么,都没有画出任何东西,我只是得到一个黑色的屏幕(所以我想有些东西被绘制,否则它将是一个透明的窗口,但它绝对不是我想要的).这是我班级的相关代码:
class ClassThing:
def __init__(self):
self.Splash = True
glutInit(sys.argv)
def TexFromPNG(self, filename):
img = Image.open(filename)
img_data = numpy.array(list(img.getdata()), numpy.uint8)
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, texture)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
return texture
def run(self):
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(256,224)
self.window = glutCreateWindow("GL")
glutDisplayFunc(self.draw)
glClearColor(0,0,0,0)
glEnable(GL_TEXTURE_2D)
glEnable(GL_VERTEX_ARRAY)
self.MainTex = glGenTextures(1)
self.SplashTex = self.TexFromPNG("Resources/Splash.png")
glutMainLoop()
def draw(self):
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
if self.Splash:
glBindTexture(GL_TEXTURE_2D, self.SplashTex)
else:
glBindTexture(GL_TEXTURE_2D, self.MainTex)
glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) …Run Code Online (Sandbox Code Playgroud) 我一直在研究一个使用Python和OpenGL的项目.我之前发布了类似的问题,但我已经做了一些研究并转而使用了不推荐的函数.按照本教程(显然将其翻译成Python版本),我最终得到了这段代码:
import sys
import OpenGL
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GLUT.freeglut import *
from OpenGL.arrays import vbo
import pygame
import Image
import numpy
class AClass:
def __init__(self):
self.Splash = True #There's actually more here, but it's impertinent
def TexFromPNG(self, filename):
img = Image.open(filename) # .jpg, .bmp, etc. also work
img_data = numpy.array(list(img.getdata()), 'B')
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, texture)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameterf(GL_TEXTURE_2D, …Run Code Online (Sandbox Code Playgroud)