Yai*_*aon 5 c python numpy wrapper python-2.7
我正在包装一个C文件,所以我可以在python中使用它.C函数的输出是双精度数组.我希望这是python中的一个numpy数组.我得到了垃圾.这是一个生成错误的示例.
首先,C文件(专注于最后一个函数定义,其他一切应该没问题):
#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;
}
Run Code Online (Sandbox Code Playgroud)
编译顺利(根据我的理解 - 我使用了编译所有内容的python脚本).
在python中,我运行以下脚本来测试我的新模块:
try:
import _tmp
res = _tmp.error()
print(res)
except:
print("fail")
Run Code Online (Sandbox Code Playgroud)
我在屏幕上看到的结果是垃圾.我试着替换(int)NPY_FLOAT
,(int)NPY_FLOAT32, (int)NPY_FLOAT64, (int)NPY_DOUBLE
我仍然得到垃圾.我正在使用python2.7.
谢谢!!!
编辑:按照下面的答案,我将最后一个功能更改为:
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;
}
Run Code Online (Sandbox Code Playgroud)
现在python显示一个空数组.
尝试改变这个:
static PyObject *_aux_error(PyObject *self) {
Run Code Online (Sandbox Code Playgroud)
对此:
static PyObject *_aux_error(PyObject *self, PyObject *args) {
Run Code Online (Sandbox Code Playgroud)
Python将传递args
参数,即使您没有使用它定义函数.
您的代码仍然存在根本问题.您已使用数组创建了一个numpy数组,该数组vector
位于堆栈中.当_aux_error
返回时,内存被回收,并可能被重用.
您可以使用PyArray_SimpleNew()
分配numpy数组创建数组,然后复制vector
到数组的数据:
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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我将类型更改为NPY_DOUBLE
; NPY_FLOAT
是32位浮点类型.
在评论中,您询问了有关动态分配内存的问题_aux_error
.以下是可能有用的示例的变体.数组的长度仍然是硬编码的dims
,因此它并不完全通用,但它可能足以解决注释中的问题.
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;
}
Run Code Online (Sandbox Code Playgroud)