Calling C++ and user-mode APIs from Python

1. Introduction

This post shows how to call C and C++ functionality from Python using Python standard library`s C type. For its official reference , see :

https://docs.python.org/2/library/ctypes.html

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 :

https://docs.python.org/2/extending/extending.html

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 :

http://en.cppreference.com/w/cpp/language/language_linkage

https://stackoverflow.com/questions/1041866/in-c-source-what-is-the-effect-of-extern-c

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 :

int                              c_int

int*                            POINTER(c_int)

int**                          POINTER(POINTER(c_int))

char*                         c_char_p

char**                       POINTER(c_char_p)

void*                          c_void_p

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 :

python_win32_console_color

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 :

pythonx11

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s