Related Articles

# Python | Opaque Pointers in C extension modules

• Last Updated : 27 Mar, 2019

Let’s discuss an extension module that needs to handle a pointer to a C data structure, without exposing any internal details of the structure to Python. Opaque data structures can be easily handled by wrapping them inside capsule objects as shown in the code snippet below.

Code #1 :

 `typedef` `struct` `Point``{``    ``double` `x, y;``} Point;`` ` `extern` `double` `distance(Point *p1, Point *p2);`

Refer Prev Article to find the distance() function – Using C codes in Python.

Code #2 : Code given is an extension code that wraps the Point structure and `distance()` function using capsules.

 `/* Destructor function for points */``static` `void` `del_Point(PyObject * obj)``{``    ``free``(PyCapsule_GetPointer(obj, ``"Point"``));``}`` ` `/* Utility functions */``static` `Point * PyPoint_AsPoint(PyObject * obj)``{``    ``return` `(Point *) PyCapsule_GetPointer(obj, ``"Point"``);``}``static` `PyObject * PyPoint_FromPoint(Point * p, ``int` `must_free)``{``    ``return` `PyCapsule_New(p, ``"Point"``, must_free ? del_Point : NULL);``}`` ` `/* Create a new Point object */``static` `PyObject * py_Point(PyObject * self, PyObject * args)``{``    ``Point * p;``    ``double` `x, y;``    ``if` `(! PyArg_ParseTuple(args, ``"dd"``, &x, &y))``    ``{``        ``return` `NULL;``    ``}``    ``p = (Point *) ``malloc``(``sizeof``(Point));``    ``p->x = x;``    ``p->y = y;``    ``return` `PyPoint_FromPoint(p, 1);``}`` ` `static` `PyObject * py_distance(PyObject * self, PyObject * args)``{``    ``Point * p1, *p2;``    ``PyObject * py_p1, *py_p2;``    ``double` `result;``    ``if` `(! PyArg_ParseTuple(args, ``"OO"``, &py_p1, &py_p2))``    ``{``        ``return` `NULL;``    ``}``    ``if` `(!(p1 = PyPoint_AsPoint(py_p1)))``    ``{``        ``return` `NULL;``    ``}``    ``if` `(!(p2 = PyPoint_AsPoint(py_p2)))``    ``{``        ``return` `NULL;``    ``}``    ``result = distance(p1, p2);``    ``return` `Py_BuildValue(``"d"``, result);``}`

Code #3 : Using the above function in Python

 `import` `sample`` ` `pt1 ``=` `sample.Point(``2``, ``3``)``pt2 ``=` `sample.Point(``4``, ``5``)`` ` `print` `(``"pt1 : "``, pt1)``print` `(``"\npt2 : "``, pt2)`` ` `print` `(``"Distance : "``, sample.distance(p1, p2))`

Output :

```pt1 : <capsule object "Point" at 0x1004ea330>

pt2 : <capsule object "Point" at 0x1005d1db0>

Distance : 2.8284271247461903
```

• Capsules are similar to a typed C pointer.
• They hold a generic pointer along with an identifying name and can be easily created using the `PyCapsule_New()` function.
• `PyCapsule_GetPointer()` function is used to extract the pointer contained inside a capsule.
• Garbage collection and memory management is a tricky part that concerns about the capsules.
• `PyPoint_FromPoint()` function accepts a must_free argument that indicates whether the underlying Point * structure is to be collected when the capsule is destroyed.

Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.

To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course. And to begin with your Machine Learning Journey, join the Machine Learning – Basic Level Course

My Personal Notes arrow_drop_up