扩展蟒蛇与C,返回numpy的数组给垃圾 [英] Extend python with C, return numpy array gives garbage
问题描述
我环绕C文件,所以我可以在Python中使用它。 C函数的输出是双打的数组。我希望这是一个Python numpy的数组。我得到的垃圾。下面是生成错误的例子。
I am wrapping a C file so I can use it in python. The output of the C function is an array of doubles. I want this to be a numpy array in python. I get garbage. Here's an example that generates the error.
首先,C文件(集中在最后一个函数的定义,一切应该是OK):
First, the C file (focus on the last function definition, everything else should be OK):
#include <Python.h>
#include <numpy/arrayobject.h>
#include <stdio.h>
static char module_docstring[] =
"docstring";
static char error_docstring[] =
"generate the error";
static PyObject *_aux_error(PyObject *self, PyObject *args);
static PyMethodDef module_methods[] = {
{"error", _aux_error, METH_VARARGS, error_docstring},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC init_tmp(void) {
PyObject *m = Py_InitModule3("_tmp", module_methods, module_docstring);
if (m == NULL)
return;
/* Load `numpy` functionality. */
import_array();
}
static PyObject *_aux_error(PyObject *self ,PyObject *args) {
double vector[2] = {1.0 , 2.0};
npy_intp dims[1] = { 2 };
PyObject *ret = PyArray_SimpleNewFromData(1, dims, (int)NPY_FLOAT , vector );
return ret;
}
编译去确定(从我的理解 - 我用一个Python脚本编译一切)
Compilation goes OK (from what I understand - I used a python script that compiles everything).
在蟒蛇,我运行下面的脚本来测试我的新模块:
In python, I run the following script to test my new module:
try:
import _tmp
res = _tmp.error()
print(res)
except:
print("fail")
我在屏幕上看到的结果是垃圾。我试图取代(INT)NPY_FLOAT
与(INT)NPY_FLOAT32,(INT)NPY_FLOAT64,(INT)NPY_DOUBLE
和我仍然得到垃圾。
我使用python2.7。
The result I see on the screen is garbage. I tried substituting (int)NPY_FLOAT
with (int)NPY_FLOAT32, (int)NPY_FLOAT64, (int)NPY_DOUBLE
and I still get garbage.
I am using python2.7.
谢谢!
修改:按照下面的答案,我改变了最后一个功能:
EDIT: following the answer below, I changed the last function to:
static PyObject *_aux_error(PyObject *self, PyObject *args) {
double *vector = calloc(2, sizeof(double));
vector[0] = 1.0;
vector[1] = 2.0;
npy_intp *dims = calloc(1 , sizeof(npy_intp));
dims[1] = 2;
PyObject *ret = PyArray_SimpleNewFromData(1, dims, (int)NPY_FLOAT , &vector );
return ret;
}
现在蟒蛇显示一个空数组。
Now python shows an empty array.
推荐答案
尝试改变这一点:
static PyObject *_aux_error(PyObject *self) {
这样:
static PyObject *_aux_error(PyObject *self, PyObject *args) {
Python将通过 ARGS
的说法,即使你不使用它定义的功能。
Python will pass the args
argument, even if you don't define your function with it.
有仍然与code的一个根本问题。你已经创建使用数组numpy的阵列,矢量
,也就是在堆栈中。当 _aux_error
的回报,内存被回收,并可能被重用。
There's still a fundamental problem with your code. You have created a numpy array using an array, vector
, that is on the stack. When _aux_error
returns, that memory is reclaimed and might be reused.
您可以用创建数组 PyArray_SimpleNew()
来分配numpy的数组,然后复制矢量
来的阵列的数据:
You could create the array using PyArray_SimpleNew()
to allocate the numpy array, and then copy vector
to the array's data:
static PyObject *_aux_error(PyObject *self, PyObject *args)
{
double vector[2] = {1.0 , 2.0};
npy_intp dims[1] = {2};
PyObject *ret = PyArray_SimpleNew(1, dims, NPY_DOUBLE);
memcpy(PyArray_DATA(ret), vector, sizeof(vector));
return ret;
}
请注意,我改变的类型 NPY_DOUBLE
; NPY_FLOAT
是32位浮点类型。
Note that I changed the type to NPY_DOUBLE
; NPY_FLOAT
is the 32 bit floating point type.
在一个评论,你问动态地分配在 _aux_error
的内存。下面是可能有用的示例的变化。数组的长度仍然是变暗硬$ C $光盘
,所以它是不完全一般,但它可能足以从注释解决的问题。
In a comment, you asked about dynamically allocating the memory in _aux_error
. Here's a variation of the example that might be useful. The length of the array is still hardcoded in dims
, so it isn't completely general, but it might be enough to address the question from the comments.
static PyObject *_aux_error(PyObject *self, PyObject *args)
{
double *vector;
npy_intp dims[1] = {5};
npy_intp k;
PyObject *ret = PyArray_SimpleNew(1, dims, NPY_DOUBLE);
vector = (double *) PyArray_DATA(ret);
/*
* NOTE: Treating PyArray_DATA(ret) as if it were a contiguous one-dimensional C
* array is safe, because we just created it with PyArray_SimpleNew, so we know
* that it is, in fact, a one-dimensional contiguous array.
*/
for (k = 0; k < dims[0]; ++k) {
vector[k] = 1.0 + k;
}
return ret;
}
这篇关于扩展蟒蛇与C,返回numpy的数组给垃圾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!