2

I wish to generate arrays in a C extension module and pass them back to python.

The following code works for 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])

Then building and installing:

>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.]])

However, what is the equivalent of this for python3? I only found a way to return scalar variables:

>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

How can I return arrays?

Ginger
  • 21
  • 2

1 Answers1

1

I think the issue is that PyArray_FromDims is a very old API function that is no longer recommended, and may have been removed from the Numpy headers. I don't know why it seems to work for Python 2, but it's possible that you have an older version of Numpy installed there.

I suggest you use PyArray_ZEROS instead, which has basically the same interface with an additional parameter to mark if the array should be Fortran contiguous (you probably want to set this to 0). If you want to fill the array to something other than zero then pick a different function (read the documentation I have linked).

DavidW
  • 29,336
  • 6
  • 55
  • 86