在 C++ 中嵌入 Python 时无法将参数传递给 Python 函数 foobar.pyfoobar.cpp输出

问题描述

我在我的 C++ 代码中嵌入了一个 Python 模块,并且我正在使用 Python/C API。 我需要调用 Python 模块函数获取结果。 该函数获取一个无符号整数和一个双精度数作为输入参数并输出一个列表。 我使用以下方法调用函数

unsigned int num_units = 10;
double max_time = 15.12;
PyObject *output_list = PyObject_CallMethod(sample_object,"get_list","(I)",num_units,"(d)",max_time);

get_list 函数添加打印语句时,我从 Python 方面注意到参数没有传递给函数。 我想我的语法可能不对?

更新: 我最初使用以下语法尝试了@Ruzihm 的建议,但没有成功。事实证明,python 代码中存在其他语法问题,这些问题阻止了代码的正确执行,而且我的错误检查都没有发现它。修复问题后,代码运行完美。

PyObject *output_list = PyObject_CallMethod(sample_object,"Id",max_time);

我也尝试将 CallMethodobjArgs 与以下代码一起使用:

PyObject *func_obj,*num_units_obj,*max_time_obj;

num_units_obj = PyLong_FromUnsignedLong(num_units);
max_time_obj = PyFloat_FromDouble(max_time);
func_obj = PyUnicode_FromString("get_list");

PyObject *output_list = PyObject_CallMethodobjArgs(sample_object,func_obj,num_units_obj,max_time_obj,NULL);

Py_DECREF(func_obj);
Py_DECREF(num_units_obj);
Py_DECREF(max_time_obj);

Python 函数定义也如下所示:

def get_list(self,max_time):

非常感谢任何帮助。

解决方法

应该只有一个格式字符串(可能为 NULL),后跟任何/所有输入。括号用于指定大小为零或一的元组,您没有提到需要。所以,就这样做:

PyObject *output_list = PyObject_CallMethod(sample_object,"get_list","Id",num_units,max_time);

完整示例:

foobar.py

class foobar():
     def get_list(self,max_time):
         print(num_units)
         print(max_time)

foobar.cpp

#define PY_SSIZE_T_CLEAN
#include "python3.6m/Python.h"
#include <iostream>

int main() {
    PyObject *module,*dict,*python_class,*sample_object; 

    setenv("PYTHONPATH",".",1);
    Py_Initialize();  

    module = PyImport_ImportModule("foobar");
    if (module == nullptr)
    {
        std::cout << "Failed to import module.";
        return 1;
    }
 
    dict = PyModule_GetDict(module);
    if (dict == nullptr)
    {
        std::cout << "Failed to get module dict.";
        return 1;
    }
    Py_DECREF(module);
 
    python_class = PyDict_GetItemString(dict,"foobar");
    if (python_class == nullptr)
    {
        std::cout << "Failed to get class.";
        return 1;
    }
    Py_DECREF(dict);
 
    sample_object = PyObject_CallObject(python_class,nullptr);
    if (sample_object == nullptr)
    {
        std::cout << "Failed to instantiate object.";
        return 1;
    }
    Py_DECREF(python_class);
 

    unsigned int num_units = 10;
    double max_time = 15.12;
 
    PyObject *output_list = PyObject_CallMethod(sample_object,max_time);

    /* Alternatively,use PyObject_CallMethodObjArgs
    PyObject *func_obj,*num_units_obj,*max_time_obj;

    num_units_obj = PyLong_FromUnsignedLong(num_units);
    max_time_obj = PyFloat_FromDouble(max_time);
    func_obj = PyUnicode_FromString("get_list");

    PyObject *output_list = PyObject_CallMethodObjArgs(sample_object,func_obj,num_units_obj,max_time_obj,NULL);

    Py_DECREF(func_obj);
    Py_DECREF(num_units_obj);
    Py_DECREF(max_time_obj);
    */
}

(基于 this answer's 代码)

输出

$ g++ foobar.cpp -lpython3.6m;./a.out
10
15.12