问题描述
我想访问一些我用C代码编写的python函数。我的python函数之一接收一个numpy数组作为输入。在我的C代码中,此数组分配在动态内存中。每当我的python函数被调用时,我都会收到一个分段错误,而且我不确定自己在做什么错。我试图将N,O,O&传递给Py_BuildValue函数,但我一直得到相同的结果。
这是python的简化代码。
#Python simple function that receives pointer to array
#!/usr/bin/python3
import numpy as np
def getNumpyArrayPointer(pointer):
data = np.ctypeslib.as_array(pointer,shape=(1000,1)).astype(np.int32) #Doesn't matter if I comment out this line. Fault continues
print('Python function getNumpyArrayPointer() called')
return data
这是C简化代码
#include <iostream>
#include <Python.h>
#include "pyhelper.h"
int capitest()
{
Py_Initialize();
PyObject* sysPath = PySys_Getobject((char*)"path");
PyObject* programName = PyUnicode_FromString("path-to-python-script");
PyList_Append(sysPath,programName);
Py_DECREF(programName);
PyObject* pName = PyUnicode_FromString("python-script-name");
PyObject* pModule = PyImport_Import(pName);
PyObject* pValue;
cpyObject pFunc;
PyObject* args;
if(pModule)
{
pFunc = PyObject_GetAttrString(pModule,"getNumpyArrayPointer");
uint32_t *array = (uint32_t *)malloc (1000);
args = Py_BuildValue("(N)",array );
if(pFunc && PyCallable_Check(pFunc))
{
printf("Calling getNumpyArrayPointer\n");
pValue = PyObject_CallObject(pFunc,args);
Py_DECREF(args);
printf("Called getNumpyArrayPointer\n");
if (PyErr_Occurred())
{
PyErr_Print();
return 0;
}
}
else
{
printf("ERROR: function getNumpyArrayPointer()\n");
}
}
else
{
printf("ERROR: Module not imported\n");
}
Py_Finalize();
return 0;
}
int main()
{
capitest();
}
输出:
Calling getNumpyArrayPointer
Segmentation fault (core dumped)
解决方法
uint32_t *array = (uint32_t *)malloc (1000);
args = Py_BuildValue("(N)",array );
那是胡扯。您要告诉它数组是指向Python对象的指针,因此它将尝试管理数组的“引用计数”。
我会提出一些建议:
PyObject* pointer_as_int = PyLong_FromVoidPtr(array);
然后,您要将其传递给ctypes.cast(pointer_as_int,ctypes.POINTER(ctypes.c_uint32))
的Python对象以获取ctypes指针。例如参见ctypes: construct pointer from arbitrary integer
或者,您可以尝试直接将C指针传递给Numpy C API函数PyArray_SimpleNewFromData
-您会在Stack Overflow和其他地方找到很多示例。
请注意,一旦完成处理,您的C代码将负责释放数组。