This post shows how to call C and C++ functionality from Python using Python standard library`s C type. For its official reference , see :
Ctypes is a cross platform library therefore it can consume shared objects in Linux and also DLLs in Windows. It is quite useful in some situations :
- You can create external test harnesses for your C++ projects by simply exposing a C interface
- When you expose your C++ via C linkage , you might also be able to use that from other languages such as Java and C#
- You can add new functionality to Python without dealing with ugly Python extension module APIs.
- To quickly try POSIX/Linux or Windows APIs or any other external SDK that exposes functionality via C linkage
You can download all example source code from https://github.com/akhin/cplusplus_dev_toys/tree/master/calling_cpp_from_python
2. Why Ctypes instead of extension modules
I prefer using Ctypes instead of writing Python extension modules because I find Python module extension API very cumbersome and hard to read. On the other hand the only thing you need to expose your C++ functionality to Python is only using C linkage to use Python ctypes. Below you can see the reference page to develop Python extension modules :
3. C Linkage and extern “C”
You will need C linkage in order to expose functionality in your existing C++ code. Therefore you will need to create C functions in an extern “C” block. Extern “C” block is necessary so that the compiler can generate non-mangled function names. For more information :
4. Test shared object
Below you can see our shared object`s code. It exposes a struct , functions with call by value and call by reference and uses C++ class instantiation in one of functions. Notice that it uses extern “C” for the exposed functions :
In order to build the code , you need :
g++ -shared -fPIC libtest.cpp -o libtest.so
5. Python code using the test shared object
First , will show the all code that consumes libtest.so :
Explanations are as below :
a. Importing ctypes library in line 2
b. We use cdll.LoadLibrary function to load a shared object
c. We have to specify return type and types of all arguments of a function in order to use it. You can see this in all function wrappers.
d. We can work with fundamental types by using Ctype`s mappings. Below you can see most used mappings :
void return value None
e. You can use ctype`s byref method to pass Python objects to C++ by reference.
f. You can implement callbacks using function pointer in C/C++ and CFUNCTYPE in Python ctypes library. invokeCallback in Python passes Python function callback to shared object`s function and shared object uses that callback function.
g. You can map struct to Python by using a list of tuples. Shared objects struct Foo is mapped to Python this way. And after mapping a struct , you can call function that uses that struct. For example Python initCStruct passes a Foo object to the shared object`s function.
6. Win32 example – Color in Windows Console
As another use case, you can also work directly with OS APIs. The sample below uses Windows APIs in order to use color in Windows console :
When you run it :
7. Linux example – Minimal X Window
Following the previous one , this example shows how to create a minimal X11 window by calling XWindow system`s shared object on Linux :
When executed , it looks like :