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.