Skip to content

Instantly share code, notes, and snippets.

@kanhua
Last active February 1, 2023 17:08
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save kanhua/8f1eb7c67f5a031633121b6b187b8dc9 to your computer and use it in GitHub Desktop.
Save kanhua/8f1eb7c67f5a031633121b6b187b8dc9 to your computer and use it in GitHub Desktop.
A template of writing C or C++ extension for python and numpy
#include <stdio.h>
#include <Python.h>
#include "numpy/ndarraytypes.h"
#include "numpy/ufuncobject.h"
#include "numpy/npy_3kcompat.h"
// Module method definitions
static PyObject* hello_world_c(PyObject *self, PyObject *args) {
printf("Hello, world!\n");
Py_RETURN_NONE;
}
static PyObject* hello_numpy_c(PyObject *dummy, PyObject *args)
{
PyObject *arg1=NULL;
PyObject *arr1=NULL;
int nd;
if (!PyArg_ParseTuple(args, "O", &arg1))
return NULL;
arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
/*
* my code starts here
*/
nd=PyArray_NDIM(arr1);
npy_intp *sp=PyArray_SHAPE(arr1);
printf("array dimentsion: %ld\n",*sp);
printf("Print array elements:\n");
for (int i=0; i<*sp; i++)
{
printf("%lf ",*((npy_double*)PyArray_GETPTR1(arr1,i)));
}
printf("\n");
if (arr1 == NULL)
return NULL;
nd = PyArray_NDIM(arr1); //number of dimensions
Py_DECREF(arr1);
return PyInt_FromLong(nd);
}
static PyMethodDef hello_methods[] = {
{
"hello_python", hello_world_c, METH_VARARGS,
"Print 'hello xxx'"
},
{
"hello_numpy", hello_numpy_c, METH_VARARGS,
"numpy function tester",
},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef hello_definition = {
PyModuleDef_HEAD_INIT,
"hello",
"A Python module that prints 'hello world' from C code.",
-1,
hello_methods
};
PyMODINIT_FUNC PyInit_hello(void) {
Py_Initialize();
import_array();
return PyModule_Create(&hello_definition);
}
all: hello.c setup.py
python3 setup.py build_ext --inplace
test: all
python3 test_mod.py
#!/usr/bin/env python3
# encoding: utf-8
from distutils.core import setup, Extension
def configuration(parent_package='', top_path=None):
import numpy
from numpy.distutils.misc_util import Configuration
from numpy.distutils.misc_util import get_info
#Necessary for the half-float d-type.
info = get_info('npymath')
config = Configuration('',
parent_package,
top_path)
config.add_extension('hello',
['hello.c'],
extra_info=info)
return config
if __name__ == "__main__":
from numpy.distutils.core import setup
setup(configuration=configuration)
import hello
import numpy as np
hello.hello_python()
hello.hello_numpy(np.array([1,2,3]))
@rnbguy
Copy link

rnbguy commented Mar 14, 2019

I am getting this error,

error: cannot convert ‘PyObject*’ {aka ‘_object*’} to ‘PyArrayObject*’ {aka ‘tagPyArrayObject_fields*’}
         npy_intp *sp=PyArray_SHAPE(arr1);

Edit: Ah. You code is in C. I was using C++. In C++, you need to do

PyArrayObject * np_arr1 = (PyArrayObject*)(arr1);
npy_intp *sp=PyArray_SHAPE(np_arr1);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment