【问题标题】:How can I call a method from the C API where the number of arguments is known only at runtime?如何从 C API 调用仅在运行时才知道参数数量的方法?
【发布时间】:2026-01-15 16:45:02
【问题描述】:

我正在使用 Python C API 来调用方法。目前我正在使用PyObject_CallMethodObjArgs 来执行此操作。这是一个可变参数函数:

PyObject* PyObject_CallMethodObjArgs(PyObject *o, PyObject *name, ..., NULL)

当参数的数量在编译时已知时,这绝对没问题。但是,我有一个场景,直到运行时才知道参数的数量,它们以数组的形式提供。

本质上我的问题与这个问题完全相同:How can I pass an array as parameters to a vararg function?

那里接受的答案告诉我,我的问题没有解决方案。

有没有办法绕过这个障碍。如果我无法使用PyObject_CallMethodObjArgs 解决问题,Python C API 中是否有替代函数可以满足我的需求?

例如,PyObject_Call 接受参数作为 Python 序列对象。是否可以使用此功能,或具有类似界面的功能?

【问题讨论】:

  • 请提供一些minimal reproducible example。你的问题不清楚。你用什么编程语言编写代码?
  • 我不认为编程语言是相关的。毕竟,这是一个 API,因此几乎适用于任何编程语言。
  • 每种编程语言实现都有自己的calling convention,因此您使用的实现编程语言非常相关. SBCL 与 C 不同(即我的 Linux 上的 GCC,遵循 Linux ABI)
  • 不,我认为你不明白我的问题。
  • 问题出在你的最后。别担心。

标签: python


【解决方案1】:

我不确定我是否完全错了,但 AFAICT 应该有可能

【讨论】:

  • 我应该传递什么作为callable_object 参数?我想我想知道如何让self 进入该方法。
  • 好的,我明白了,我可以使用PyObject_GetAttrString 传递对象引用和方法名称,一切都很好。我想从中得到的东西是必然的。所以答案毕竟在我的问题中!
【解决方案2】:

一种可能的方法是使用libffi,也许是通过ctypes Python 库。它知道您的ABIcalling conventions(因此在许多流行的实现中部分用汇编程序编码)并允许您调用任意签名和任意数量的任意函数。

请注意,便携式和标准C11 中有no purely standard way of doing that(不使用某些外部库,如libffi...)(请阅读n1570)。

顺便说一句,libffi 可以在任何 C 程序中使用。 ctypes 可以在任何 Python 程序中使用。

Python Embedding and extending Python 章节解释了如何从 C 调用 Python,或从 Python 调用 C。

【讨论】:

  • 这当然是可能的。就像问题的最后几段一样,我想知道是否有另一种方法可以使用 Python C API 调用方法。
  • 我不明白你的“Python C API”表达。你是用 C(然后使用 libffi)还是 Python(然后使用 ctypes)编码?
  • Python C API 在此处记录:docs.python.org/3/c-api/index.html 这是您嵌入 Python 或编写扩展模块的方式。我实际上是在 Delphi 中编写代码,所以 libffi 并非易事。
  • 这应该进入你的问题!
  • 我已经编辑了这个问题,希望能更清楚地显示我正在寻找的内容。我不认为语言特别相关。