C++调用时python时,如何传入数组做为参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++调用时python时,如何传入数组做为参数相关的知识,希望对你有一定的参考价值。

def printList(list ):
print('Star');
print len(list)
for var in list:
print var
以上是python源码,因为只是做为测试较为简单
pFunc = PyDict_GetItemString(pDict, "printList");
if (!pFunc)
exit(0);
PyObject* list = PyList_New(3);
for (size_t i = 0; i < 3; i++)
PyList_Append(list, Py_BuildValue("i", i));
PyEval_CallObject(pFunc, list);
这是C++源码,python中的方法要求传入一个列表,我按我C++代码中的做法,将一个生成好的pyobject*的列表传入时,代码无法正常执行。这边的问题出在哪?我该怎么做?谢谢。

题主,你基本操作没什么问题,有几个小地方要修改一下,修改如下:


你的源码:

PyObject* list = PyList_New(3);    
for (size_t i = 0; i < 3; i++)
PyList_Append(list, Py_BuildValue("i", i));

PyEval_CallObject(pFunc, list);

--------------------------------------------------------------------------------------

修改后,应该是这样
PyObject* pArgs = NULL;

PyObject* list = PyList_New(0);    //3改成0
pArgs = PyTuple_New(1);                 //定义1个参数

for (size_t i = 0; i < 3; i++)
PyList_Append(list, Py_BuildValue("i", i)); //这样才能用Append,
PyTuple_SetItem(pArgs, 0, list);    //将列表赋给参数
PyEval_CallObject(pFunc, list);    //传入参数,调用函数

注意事项:PyList_New(0) 初始化0的时候,应该用Append初始化
PyList_New(3) 初始化3个时候,应该用SetItem初始化
如果用Append的话,会出现[NULL, NULL, NULL]的情况

我在给一个完整的:

Python :(hello.py)      

def TestList(nlist):
        print(nlist)
        return


一般参数都是已元组形式传入的

  Py_Initialize();
 
  PyRun_SimpleString("import sys");   
PyRun_SimpleString("sys.path.append('./')");  

PyObject* pModule =NULL;
PyObject* pList = NULL;
PyObject* pFunc = NULL;
PyObject* pArgs = NULL;

  pModule = PyImport_ImportModule("hello");
  pFunc = PyObject_GetAttrString(pModule, "TestList");
  pArgs = PyTuple_New(1);
pList = PyList_New(0);
for (int i = 0; i < 3; i++)

    PyList_Append(pList, Py_BuildValue("i", i));

PyTuple_SetItem(pArgs, 0, pList);
pRet = PyEval_CallObject(pFunc, pArgs);

Py_Finalize();

最后输出的:[0, 1, 2]

参考技术A 在list后加[] 传递进去就好了 要是要改变原先的数组就要传递指针追问

这里有点不太明白的是,我的源码中多次出现过list,你的答杂所指的是python中的list还是c++中的list?因为我按你的说法都试过了,但都有语法错误。其实是,传递指针的话不应该是在这里改写成PyEval_CallObject(pFunc, &list);这样吗?

如果不麻烦的话,能否写一下试例,谢谢

追答

是 c++是&引用 你太天才了 C/C++编译器亦支持*指针(形参)传递
总之就是说 你扔给黑盒子一样东西 他不会改变那样东西 只会在另一个地址上创建并运算 当然 在黑盒子里边输出就不必考虑这些了
若是要在外部看到运算结果 可以设黑盒子返回 也可以告诉黑盒子一个地址 让他直接在地址里面操作

追问

能写个实例吗?
因为无论按哪种传址方式都无法调用该方法,我学艺不精,所以请写个实例吧。谢谢

追答

#include
#include
#define max 6

void fun(int &numbers,int a)

int *i=&(*&numbers);
for(int j=0;j<a;j++)

*i+=j;
i++;



int main()

int a[max]=0;
fun(*a,max);
for(int j=0;j<max;j++)

printf("%d,",a[j]);

system("pause");
return 0;

DEV测试代码可以使用
算法是乱七八糟的 自加都感觉效率不能见人 但是可以明显的看到 运算是在函数内部 但是外部输出时候数组已改变

本回答被提问者采纳
参考技术B 关键在于 import_array(),否则必然崩溃。

#include <Python.h>
#include <numpy/arrayobject.h>

//必须这样写!
void init_numpy()

import_array();


int fext_python_init(const char* pPath)

PyObject *pArgs = NULL;

Py_Initialize();
init_numpy();

PyObject* pArgs = PyTuple_New(1);

//将c的img数组数据转换成pyobject类型的数组数据
npy_intp dims[1] = pImage->clip.width * pImage->clip.height * 4;

//给定维度信息
PyObject *pPyArray = PyArray_SimpleNewFromData(1, dims, NPY_CHAR, pImage->buffer.data);
PyTuple_SetItem(pArgs, 1, pPyArray);

……

从 C++ 调用 python 函数时如何将 C++ 类作为参数传递?

【中文标题】从 C++ 调用 python 函数时如何将 C++ 类作为参数传递?【英文标题】:How to pass C++ classes as arguments when calling python functions from C++? 【发布时间】:2014-12-07 23:33:02 【问题描述】:

我正在编写一个需要加载 Python 模块并调用该模块中的函数的 C++ 应用程序。 应用程序需要将 C++ 分类作为参数传递给 python 函数。 我设法从 C++ 代码中调用 python 代码,但我只设法将“原始”类型作为参数传递。

我使用 SWIG 创建包装器/接口,但我找不到如何将我的 C++ 类从应用程序转换为 PyObject* 以便将其作为参数传递给 python 函数。

您知道我在哪里可以找到有关如何执行从 C++ 转换为 PyObject* 的信息吗?

【问题讨论】:

【参考方案1】:

Boost 有一个 Python 接口库,可能对你有帮助。

check it out

heres the documentation on functions

【讨论】:

【参考方案2】:

我仍然没有解决方案,我只有以下解决方法: 1. 我从实例创建一个 PyObject,并将它传递给 python 函数。 2. python 代码,使用 SWIG 生成的库中的一个函数,将 PyObject 转换为该类的 python 版本。

实现:

在 C++ 文件中

MyClass myObject;
...
PyObject *parameterForPython = PyCObject_FromVoidPtr(&myObject, NULL); // step 1
PyTuple_SetItem(pyArgs, 0, parameterForPython);
PyObject_CallObject(pythonFunctionObject, pyArgs);

在 swig 接口文件中(步骤 2 的代码):

%inline %
    MyClass *convertPyObjectToMyClass(PyObject * ptr) 
        return (MyClass *)PyCObject_AsVoidPtr(ptr)
    
%

在python模块中:

def myPythonFunction(ptr):
    myObject = cppmodule.convertPyObjectToMyClass(ptr) #step 2

【讨论】:

【参考方案3】:

您考虑过使用SWIG_NewPointerObj(ptr, type, flags)SWIG_ConvertPtr(obj, pptr, type, flags) 吗?

您可以通过运行获得这些声明:

swig -python -external-runtime swig-python.h

【讨论】:

以上是关于C++调用时python时,如何传入数组做为参数的主要内容,如果未能解决你的问题,请参考以下文章

关于delphi调用C++的DLL中char*参数的问题

python 调用 C++的DLL,函数参数是数组怎么处理?

数组做为参数传入Oracle存储过程操作数据库

c++ 当我创建结构数组时,如何使用结构数组内的类的参数调用构造函数?

从 C++ 调用 python 函数时如何将 C++ 类作为参数传递?

当参数之一是指针数组时,如何从 C# 调用 C++ DLL