The basic structure of an extension module

An extension module written in C will have the following parts:

  • A header segment, where you include all your external libraries and Python.h
  • An initialization segment, where you define the module name and the functions in your C module
  • A method structure array to define all the functions in your module
  • An implementation segment, where you define all the functions that you would like to expose

The header segment

Header snippets are quite standard, just like a normal C module. We need to include the Python.h header file to give our C code access to the internals of the C-API. This file is present in <path_to_python>/include. We will be using an array object in our example code, hence we have included the numpy/arrayobject.h header file as well. We don't need to specify the full path of the header file here as the path resolution is taken care of in setup.py, which we will take a look at later:

/* 
Header Segment 
*/ 
 
#include <Python.h> 
#include <math.h> 
#include <numpy/arrayobject.h> 
Initialization Segment 

The initialization segment

The initialization segment starts with the following:

  1. A call to a PyMODINIT_FUNC macro. This macro is defined in the Python header and will always be called before you start defining your module.
  2. The next line defines the initialization function and is called by the Python interpreter when the function is loaded. The function name has to be in the init<module_name> format, the name of the module and functions that your C code is going to expose.

The body of this function contains a call to Py_InitModule3, which defines the name of the module and the functions in it. The general structure of this function is as follows:

(void)Py_InitModule3(name_of_module, method_array, Docstring) 

The final call to import_array()is a NumPy-specific function, which is required if your functions are using Numpy Array objects. This ensures that the C-API is loaded so that the API table is available if your C++ code uses the C-API. Failure to call this function and use other NumPy API functions will most likely result in a segmentation fault error. You are advised to read about import_array() and import_ufunc() in the NumPy documentation:

/* 
Initialization module 
*/ 
 
 
PyMODINIT_FUNC 
initnumpy_api_demo(void) 
{ 
(void)Py_InitModule3("numpy_api_demo", Api_methods, 
         "A demo to show Python and Numpy C-API"); 
import_array(); 
} 

The method structure array

In this segment, you will define the array of methods that your module is going to expose to Python. We have defined two functions here that square its argument. One takes a plain Python double value as input and the second method operates on Numpy Arrays. The PyMethodDef structure can be defined in C as follows:

Struct PyMethodDef { 
char *method_name; 
PyCFunction method_function; 
int method_flags; 
char *method_docstring; 
}; 

Here is the description of the members of this structure:

  • method_name: The name of the function goes here. This will be the name by which the function will be exposed to the Python interpreter.
  • method_function: This variable holds the name of the C function that is actually called when method_name is invoked in the Python interpreter.
  • method_flags: This tells the interpreter which of the three signatures our function is using. This flag usually has a value of METH_VARARGS. This flag can be combined with METH_KEYWORDS if you want to allow keyword arguments into your function. This can also have a value of METH_NOARGS, which would indicate that you do not want to accept any arguments.
  • method_docstring: This is the docstring for the function.

This structure needs to be terminated with a sentinel that consists of NULL and 0 as shown in the following example:

 
/* 
Method array structure definition 
*/ 
static PyMethodDefApi_methods[] = 
{ 
{"py_square_func", square_func, METH_VARARGS, "evaluate the squares"}, 
{"np_square", square_nparray_func, METH_VARARGS,  "evaluates the square in numpy array"}, 
{NULL, NULL, 0, NULL} 
}; 

The implementation segment

The implementation section is the most straightforward section. This is where the C definition of your methods will go. Here, we will study two functions that square their input values. The complexity of these functions is kept low so as to let you focus on the structure of the method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.220.92