Возвращение массива из расширения Python3 C - PullRequest
1 голос
/ 11 марта 2019

Я хочу сгенерировать массивы в модуле расширения C и передать их обратно в python.

Следующий код работает для python2 :

C_generate_array.c:

#include "Python.h"
#include "arrayobject.h"
#include "C_generate_array.h"
#include <assert.h>

static PyMethodDef C_generate_arrayMethods[] = {
    {"get_array", get_array, METH_VARARGS},
    {NULL, NULL}     /* Sentinel - marks the end of this structure */
};

#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef cModPyDem =
{
    PyModuleDef_HEAD_INIT,
    "C_generate_array", /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    C_generate_arrayMethods
};
PyMODINIT_FUNC PyInit_C_generate_array(void)
{
    return PyModule_Create(&cModPyDem);
}
#else
void initC_generate_array()  {
    (void) Py_InitModule("C_generate_array", C_generate_arrayMethods);
    import_array();  // Must be present for NumPy.  Called first after above line.
}
#endif

static PyObject *get_array(PyObject *self, PyObject *args)
{
    int dims[2];
    dims[0]=dims[1]=2;
    PyArrayObject *matout;
#if PY_MAJOR_VERSION >= 3
    //what to do here?
    return PyLong_FromLong(1);
#else
    matout = (PyArrayObject *) PyArray_FromDims(2,dims,NPY_DOUBLE);
    return PyArray_Return(matout);
#endif
}

C_generate_array.h:

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#if PY_MAJOR_VERSION >= 3
#define IS_PY3K
#endif

typedef int bool;
#define true 1
#define false 0


static PyObject *get_array(PyObject *self, PyObject *args);

C_generate_array_setup.py:

from distutils.core import setup, Extension
module1 = Extension('C_generate_array',
                    include_dirs = ['path_to_python/lib/python3.5/','path_to_python/lib/python3.5/site-packages/numpy/core/include/numpy/'],
                    sources = ['C_generate_array.c'])
setup (name = 'C_generate_array',
       version = '1.0',
       description = 'Example',
       ext_modules = [module1])

Затем сборка и установка:

>sudo python2.7 C_generate_array_setup.py build
>sudo python2.7 C_generate_array_setup.py install
>python2.7
>>> import C_generate_array
>>> C_generate_array.get_array()
array([[0., 0.],
       [0., 0.]])

Однако, что эквивалентно этому для python3?Я только нашел способ вернуть скалярные переменные:

>sudo python3.5 C_generate_array_setup.py build
>sudo python3.5 C_generate_array_setup.py install
>python3.5
>>> import C_generate_array
>>> C_generate_array.get_array()
1

Как я могу вернуть массивы?

1 Ответ

0 голосов
/ 13 марта 2019

Я думаю, проблема в том, что PyArray_FromDims - это очень старая функция API, которая больше не рекомендуется и, возможно, была удалена из заголовков Numpy.Я не знаю, почему он работает для Python 2, но возможно, что у вас установлена ​​более старая версия Numpy.

Я предлагаю вам использовать PyArray_ZEROS, чтоимеет в основном тот же интерфейс с дополнительным параметром, чтобы пометить, должен ли массив быть непрерывным по Фортрану (вы, вероятно, хотите установить его в 0).Если вы хотите заполнить массив чем-то отличным от нуля, выберите другую функцию (прочитайте документацию, на которую я ссылался).

...