python 结构体数组_将结构数组从Python传递给C

[更新:问题已解决!参见文章底部]

我需要允许Python开发人员将一组打包数据(在这种情况下)通过API插入到API中,这是通过Python C API手动暴露的一系列C++接口。我的初步印象是使用ctypes Structure类来实现这样的接口:class Vertex(Structure):

_fields_ = [

('x', c_float),

('y', c_float),

('z', c_float),

('u', c_float),

('v', c_float),

('color', c_int)

]

verts = (Vertex * 3)()

verts[0] = Vertex(0.0, 0.5, 0.0, 0.0, 0.5, 0xFF0000FF)

verts[1] = Vertex(0.5, -0.5, 0.0, 0.5, -0.5, 0x00FF00FF)

verts[2] = Vertex(-0.5, -0.5, 0.0, -0.5, -0.5, 0x0000FFFF)

device.ReadVertices(verts, 3) # This is the interfaces to the C++ object

其中我要传递给的函数具有以下签名:

^{pr2}$

Python包装器如下所示:static PyObject* Device_ReadVertices(Py_Device* self, PyObject* args)

{

PyObject* py_verts;

int count;

if(!PyArg_ParseTuple(args, "Oi", &py_verts, &count))

return NULL;

// This Doesn't Work!

Vertex* verts = static_cast(PyCObject_AsVoidPtr(py_verts));

self->device->ReadVertices(verts, count);

Py_RETURN_NONE;

}

当然,我遇到的最大问题是:我可以检索结构的PyObject,但我不知道如何将其转换为正确的类型。上面的代码失败得很惨。那么,我到底该如何允许用户从Python传递这种数据呢?在

现在,有两件事要考虑:首先,我已经有了相当多的Python/C++层,我对它非常满意(我远离SWIG,这样我可以有更多的灵活性)。我不想重新编写代码,所以我更喜欢一个与C API本机工作的解决方案。其次,我确实希望在我的C++代码中预先定义顶点结构,所以我不希望用户需要在Python中重新定义它(这样减少错误),但是我不知道如何暴露这样一个连续的结构。第三,我没有理由尝试ctypes结构,除了不知道另一种方法。欢迎提出任何建议。最后,由于这是一个图形应用程序(你可能已经猜到了),我更喜欢一个更快的方法,而不是一个方便的方法,即使更快的方法需要更多的工作。在

谢谢你的帮助!我仍然对python扩展有自己的看法,所以在一些比较棘手的部分获得社区的意见是很有帮助的。在

[解决方案]

首先,感谢每一个提出自己想法的人。最终的答案是由许多小道消息加起来的。最后,我发现了:山姆的使用建议结构包结果钱是对的。看到我使用的是Python 3,我不得不稍微调整一下,但是当我说了这么多之后,屏幕上出现了一个三角形:verts = bytes()

verts += struct.pack("fffffI", 0.0, 0.5, 0.0, 0.0, 0.5, 0xFF0000FF)

verts += struct.pack("fffffI", 0.5, -0.5, 0.0, 0.5, -0.5, 0x00FF00FF)

verts += struct.pack("fffffI", -0.5, -0.5, 0.0, -0.5, -0.5, 0x0000FFFF)

device.ReadVertices(verts, 3)

现在我的元组解析如下所示:static PyObject* Device_ReadVertices(Py_Device* self, PyObject* args)

{

void* py_verts;

int len, count;

if(!PyArg_ParseTuple(args, "y#i", &py_verts, &len, &count))

return NULL;

// Works now!

Vertex* verts = static_cast(py_verts);

self->device->ReadVertices(verts, count);

Py_RETURN_NONE;

}

请注意,即使我在本例中没有使用len变量(虽然在最终产品中我会使用),但我需要使用'y#'而不是仅使用'y'来解析元组,否则它将在第一个NULL处停止(根据文档)。同样要考虑的是:像这样的void*转换是相当危险的,所以请加载比我这里显示的更多的错误检查!在

所以,干得好,快乐的一天,打包回家,是吗?在

等等!别这么快!还有更多!在

对这一切的结果感觉很好,我突发奇想,决定看看我之前的尝试是否仍然失败,并回到本文中的第一个python片段。(当然,使用新的C代码)和。。。成功了!结果与结构包版本!真 的!在

所以这意味着您的用户可以选择如何提供这类数据,并且您的代码可以不做任何更改就处理这两种数据。我个人会鼓励类型结构方法,因为我认为它更容易阅读,但实际上它是任何用户满意的。(见鬼,如果他们愿意的话,他们可以手动键入一个十六进制的字节串。它起作用了。我试过了。)

老实说,我认为这是最好的结果,所以我欣喜若狂。再次感谢大家,祝其他遇到这个问题的人好运!在

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值