问题标签 [python-c-api]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
1133 浏览

python - PyEval_CallObject 偶尔会在循环中失败

我在 Python C API 上有点挣扎。我正在调用 python 方法以大约 60hz 做一些游戏 AI。它在大多数情况下都有效,但每秒左右对 PyEval_CallObject 的调用会导致返回 NULL 值。如果我正确检测到错误并继续循环,则下一秒左右一切正常,然后错误再次发生。

我怀疑我在引用计数方面做错了,但我不知道它是什么:

是的,我每次迭代都导入模块。那有必要吗?如果我将 pAiModule 存储为全局,大约一秒钟后我会遇到严重崩溃。

我还没能找到如何提取异常,要么......没有测试每个异常

我什至接近做到这一点吗?就像我说的,它主要是有效的,但我真的很想了解为什么我会出错。

预先感谢您的任何帮助。

0 投票
1 回答
952 浏览

python - 分配到 Python 3.x 缓冲区中 itemsize > 1

我正在尝试通过 Python 3.x 缓冲区接口公开图像像素信息的缓冲区(32 位 RGBA)。经过相当多的玩耍,我能够像这样工作:

在 python 中,我可以像这样玩它:

这非常有效。但是,如果我可以使用完整的像素值(int,4 字节)而不是单个字节,那就太好了,所以我修改了缓冲区获取,如下所示:

这实际上返回了数据,我可以正确读取它,但是现在任何尝试为其赋值的尝试都失败了!

在第 1 种情况下,错误告诉我'int' does not support the buffer interface,这是一种耻辱,有点令人困惑(我确实指定缓冲区格式是“I”毕竟),但我可以处理。但是,如果第 2 和第 3 种情况变得非常奇怪:两种情况都给我一个 TypeError 读数(显然,我的图像类型mismatching item sizes for "my.Image" and "bytes"在哪里)my.Image

这让我很困惑,因为我传入的数据显然与我从该元素中得到的数据大小相同。如果 itemsize 大于 1,似乎缓冲区只是停止允许分配。当然,此接口的文档非常稀疏,并且仔细阅读 python 代码并没有真正给出任何使用示例,所以我相当卡住。我是否遗漏了一些说明“当 itemsize > 1 时缓冲区基本上无用”的文档片段,我是否做错了我看不到的事情,或者这是 Python 中的错误?(针对 3.1.1 进行测试)

感谢您对这个(公认的高级)问题提供的任何见解!

0 投票
2 回答
3644 浏览

python - 将结构数组从 Python 传递到 C

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

我需要允许 python 开发人员将一组打包数据(在本例中为顶点)传递到我的 API,这是通过 Python C API 手动公开的一系列 C++ 接口。我对此的最初印象是使用 ctypes Structure 类来允许这样的接口:

我试图传递给的函数具有以下签名:

Python 包装器看起来像这样:

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

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

谢谢你的帮助!我仍然在摸索 python 扩展,所以在一些更棘手的部分获得社区输入是一个很大的帮助。

[解决方案]

所以首先,感谢所有提出想法的人。最终的答案是很多小花絮。最后,我发现:Sam 关于使用 struct.pack 的建议最终是正确的。看到我使用的是 Python 3,我不得不稍微调整一下,但是当一切都说完之后,实际上我的屏幕上出现了一个三角形:

我的元组解析现在看起来像这样:

请注意,即使我len在此示例中不使用变量(尽管我将在最终产品中使用),我仍需要使用 'y#' 而不是仅使用 'y' 来解析元组,否则它将在第一个 NULL 处停止(根据文档)。还要考虑:像这样的 void* 强制转换非常危险,所以请进行比我在这里展示的更多的错误检查!

所以,干得好,快乐的一天,收拾行李回家,是吗?

等待!没那么快!还有更多!

对这一切的结果感觉很好,我一时兴起决定看看我之前的尝试是否仍然失败,并恢复到这篇文章中的第一个 python 片段。(当然是使用新的 C 代码)而且……它成功了!结果与 struct.pack 版本相同!哇!

因此,这意味着您的用户可以选择他们将如何提供此类数据,并且您的代码可以在不进行任何更改的情况下处理其中任何一个。我个人会鼓励使用 ctype.Structure 方法,因为我认为它更易于阅读,但实际上它是用户喜欢的任何东西。(哎呀,如果他们愿意,他们可以手动输入十六进制的字节字符串。它有效。我试过了。)

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

0 投票
1 回答
1455 浏览

python - Python C API 中的静态变量

如何公开这样的“静态”变量

通过 C API?PyTypeObject 上唯一看起来可以工作的变量是 tp_members,但我在 PyMemberDef 中没有看到任何标志表明该成员应该是每个类,而不是每个实例。

为了更清楚一点,因为它可能会改变答案,我试图将 C 枚举暴露给 Python,以便枚举

可以在 Python 中访问为:

0 投票
1 回答
73 浏览

python - 如何使用 Python 的 C-API 生成特定的 unicode 字符?

我正在编写一个 Python 扩展,它通过 Py_UNICODE 数组运行,找到特定的(ASCII,如果重要的话)字符,即“\”或“\n”,并为它找到的每个字符做一些额外的事情。

有没有办法将这些字符写成文字?如果不是,那么为它们获取 Py_UNICODE 的正确方法是什么,请记住 Py_UNICODE 的大小和内部表示可能因系统而异?

0 投票
1 回答
328 浏览

python - 从 Python C API 获取回溯

我有一个 Python C API 扩展模块,它偶尔会出现无意义的“MemoryError”。这显然不是模块异常处理程序处理的错误。如何获得更多信息的错误回溯,以便找出扩展模块中出了什么问题?

也许问题应该是,鉴于我确实有扩展模块源代码,我应该怎么做才能在 MS Windows 上使用 MSVC 获得它的可调试版本?

0 投票
2 回答
190 浏览

c++ - 使用 Python C API 实现 PyMyType_Check 方法?

Python 提供的所有类型都有一个检查方法(即PyList_Check),它允许您检查任意PyObject*值是否实际上是特定类型。

我怎样才能为我自己的类型实现这个?我没有在网上找到任何好的东西,尽管这似乎是一件很正常的事情。

另外,也许我只是在查看大型源代码树方面很糟糕,但我终生无法PyList_Check在 Python (2.5) 源代码中找到实现或其任何同伴。

0 投票
1 回答
416 浏览

python - 在 python3 中将 PyBytesObject 类型转换为 PyUnicodeObject 类型

如何将 pyunicodeobject 类型转换为 pybytesobject 类型?

例子:

结果出现总线错误。

0 投票
2 回答
6129 浏览

python - numpy 数组 C api

我有一个返回 std::vector 的 C++ 函数,我想在 python 中使用它,所以我使用的是 C numpy api:

这是我从 python 调用它的方式:

发生的情况是:第一次打印没问题,值是正确的。但是当我绘制a它们时,它们不是;在第二张印刷品中,我看到了非常奇怪的值,例如1E-308 1E-308 ...0 0 0 ...初始化的内存。我不明白为什么第一次打印没问题。

部分解决方案(不起作用):

0 投票
2 回答
2236 浏览

python - 处理 C 代码时是否有任何 Python 引用计数/垃圾收集陷阱?

只是为了它,我决定创建一个与 libpython 的 Scheme 绑定,以便您可以将 Python 嵌入到 Scheme 程序中。我已经能够调用 Python 的 C API,但我还没有真正考虑过内存管理。

mzscheme 的 FFI 的工作方式是我可以调用一个函数,如果该函数返回一个指向 a 的指针PyObject,那么我可以让它自动增加引用计数。然后,我可以注册一个终结器,它会在 Scheme 对象被垃圾回收时减少引用计数。我查看了有关引用计数的文档,乍一看并没有发现任何问题(尽管在某些情况下它可能不是最佳的)。我有什么遗漏吗?

另外,我在制作循环垃圾收集器文档的正面或反面时遇到了麻烦。在这里我需要记住什么?特别是,我如何让 Python 知道我引用了某些东西,以便在我仍在使用它时它不会收集它?