使用来自C++的任意数量的参数(在编译时未知)调用 Python 函数

Calling Python function with arbitrary number (not known at compilation time) of parameters from C++

本文关键字:未知 编译 函数 Python 调用 参数 C++ 任意数      更新时间:2023-10-16

我需要从C++调用表单的 Python 函数

def function(a, b, *c)
print(a) # Mock example
print(b) # Mock example
print(c) # Mock example

要求:我不应该修改 Python 函数。它们由用户提供,并且应具有该签名以保持一致性。

Python.h界面提供(引用自链接,不要让你不得不打开另一个页面):

  1. PyObject* PyObject_CallFunction(PyObject *callable, const char *format, ...)返回值:新引用。 调用可调用的 Python 对象,具有可变数量的 C 参数。C 参数使用 Py_BuildValue() 样式格式字符串进行描述。格式可以为 NULL,表示未提供任何参数。 成功时返回调用的结果,或引发异常并在失败时返回 NULL。 这相当于 Python 表达式:callable(*args)。 请注意,如果您只传递 PyObject * args,PyObject_CallFunctionObjArgs() 是一个更快的选择。

  2. PyObject* PyObject_CallFunctionObjArgs(PyObject *callable, ..., NULL)返回值:新引用。 调用可调用的 Python 对象可调用,具有可变数量的 PyObject* 参数。参数作为可变数量的参数提供,后跟 NULL。 成功时返回调用的结果,或引发异常并在失败时返回 NULL。 这相当于 Python 表达式:callable(arg1, arg2, ...)

作为c的一部分传递的参数数量在编译时是未知的。在运行时,我将它们作为指向元组的PyObject *(我们称之为cc)。假设a的输入 我将其作为名为caPyObject *,同样cb用于b,并且一个名为cfunctionPyObject *包含对function的引用。

如何拨打此电话?

我试过:

  1. PyObject_CallFunctionObjArgs(cfunction, ca, cb, cc)并且与传递format字符串的其他方法类似。但这似乎导致了 Python 中形式的调用function(a, b, (c,)).在 Python 代码中,c,不是我在cc中拥有的值的元组,而是一个 1 元素元组,第一个条目是我在cc中拥有的元素元组。

  2. 我还尝试创建一个新的PyObject *cd,特别是一个包含cacb内容作为前两个元素的PyTupleObject,其余元素是cc元素。然后我打了一个像PyObject_CallFunctionObjArgs(cfunction, cd)一样的电话.但这次Python抱怨function需要位置参数b。我假设是因为cd中的元组完全给了a.

以下方法有效:

PyObject_CallFunctionObjArgs(cfunction, ca, cb, cc, NULL)

它产生了相当于 Python 中的调用

function(a,b,*c)

你快到了:将你的cd元组传递给PyObject_CallObject