0

I am trying to run a basic example for the Python C API where I create a module with a function double_array that will double the values of a numpy array returning a new numpy array.

test1.c

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <Python.h>
#include <numpy/arrayobject.h>

static PyObject* double_array(PyObject* self, PyObject* args)
{
    PyArrayObject* input_array;
    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &input_array)) {
        return NULL;
    }

    npy_intp* dims = PyArray_DIMS(input_array);
    PyArrayObject* output_array = (PyArrayObject*) PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, NULL);

    if (output_array == NULL) {
        return NULL;
    }

    double* input_data = (double*) PyArray_DATA(input_array);
    double* output_data = (double*) PyArray_DATA(output_array);
    for (npy_intp i = 0; i < PyArray_SIZE(input_array); i++) {
        output_data[i] = 2 * input_data[i];
    }

    return (PyObject*) output_array;
}

static PyMethodDef methods[] = {
    {"double_array", double_array, METH_VARARGS, "Double each element of a numpy array"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT,
    "test1",
    "Example module",
    -1,
    methods
};

PyMODINIT_FUNC PyInit_test1(void)
{
    import_array();
    return PyModule_Create(&module);
}

makefile

CC=cc
CFLAGS=-Wall -Werror -fpic -I/usr/local/include/python3.9 -I/usr/local/lib/python3.9/site-packages/numpy/core/include 
LDFLAGS=-L/usr/local/lib -shared -lpython3.9 -lm

SRC=test1.c
OBJ=$(SRC:.c=.o)
TARGET=test1.so

all: $(TARGET)

$(TARGET): $(OBJ)
        $(CC) $(LDFLAGS) -o $@ $^

%.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $<

clean:
        rm -f $(OBJ) $(TARGET)

test1.py

import numpy as np
import test1

# Create a 1D NumPy array
x = np.array([1, 2, 3], dtype=np.double)

# Call the double_array function from the test1 module
y = test1.double_array(x)

# Print the output array
print(y)

The C code compiles well without warnings or errors.

cc  -Wall -Werror -fpic -I/usr/local/include/python3.9 -I/usr/local/lib/python3.9/site-packages/numpy/core/include -c test1.c -o test1.o
cc -L/usr/local/lib -shared -lpython3.9 -lm -o test1.so 

But the execution fails:

$ python3.9 test1.py
Traceback (most recent call last):
  File "test1.py", line 2, in <module>
    import test1
ImportError: dynamic module does not define module export function (PyInit_test1)

I am using Python3.9 in FreeBSD, in case it is relevant.

M.E.
  • 4,955
  • 4
  • 49
  • 128
  • Can't reproduce on *Ubuntu*. Does it help changing *-fpic* to *-fPIC*? As a note, it's not OK to have 2 separate modules with the same name. To overcome this situation the extension one has an *UnderScore* at the beginning (*\_test1.so*). Isn't there another *test1.so* that is loaded 1st? Use *STrace* on the command to see where it's loaded from. Also `nm -S ./test1.so | grep PyInit_`. – CristiFati May 04 '23 at 16:59

0 Answers0