Here's a quick and dirty ctypes tutorial.

First, write your C library. Here's a simple Hello world example:

testlib.c

#include <stdio.h>

void myprint(void);

void myprint()
{
    printf("hello world\n");
}

Now compile it as a shared library (mac fix found here):

$ gcc -shared -Wl,-soname,testlib -o testlib.so -fPIC testlib.c

# or... for Mac OS X 
$ gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC testlib.c

Then, write a wrapper using ctypes:

testlibwrapper.py

import ctypes

testlib = ctypes.CDLL('/full/path/to/testlib.so')
testlib.myprint()

Now execute it:

$ python testlibwrapper.py

And you should see the output

Hello world
$

If you already have a library in mind, you can skip the non-python part of the tutorial. Make sure ctypes can find the library by putting it in /usr/lib or another standard directory. If you do this, you don't need to specify the full path when writing the wrapper. If you choose not to do this, you must provide the full path of the library when calling ctypes.CDLL().

This isn't the place for a more comprehensive tutorial, but if you ask for help with specific problems on this site, I'm sure the community would help you out.

PS: I'm assuming you're on Linux because you've used ctypes.CDLL('libc.so.6'). If you're on another OS, things might change a little bit (or quite a lot).

Answer from Chinmay Kanchi on Stack Overflow
🌐
Python
docs.python.org › 3 › library › ctypes.html
ctypes — A foreign function library for Python
Source code: Lib/ctypes ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these ...
Top answer
1 of 4
279

Here's a quick and dirty ctypes tutorial.

First, write your C library. Here's a simple Hello world example:

testlib.c

#include <stdio.h>

void myprint(void);

void myprint()
{
    printf("hello world\n");
}

Now compile it as a shared library (mac fix found here):

$ gcc -shared -Wl,-soname,testlib -o testlib.so -fPIC testlib.c

# or... for Mac OS X 
$ gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC testlib.c

Then, write a wrapper using ctypes:

testlibwrapper.py

import ctypes

testlib = ctypes.CDLL('/full/path/to/testlib.so')
testlib.myprint()

Now execute it:

$ python testlibwrapper.py

And you should see the output

Hello world
$

If you already have a library in mind, you can skip the non-python part of the tutorial. Make sure ctypes can find the library by putting it in /usr/lib or another standard directory. If you do this, you don't need to specify the full path when writing the wrapper. If you choose not to do this, you must provide the full path of the library when calling ctypes.CDLL().

This isn't the place for a more comprehensive tutorial, but if you ask for help with specific problems on this site, I'm sure the community would help you out.

PS: I'm assuming you're on Linux because you've used ctypes.CDLL('libc.so.6'). If you're on another OS, things might change a little bit (or quite a lot).

2 of 4
78

The answer by Chinmay Kanchi is excellent but I wanted an example of a function which passes and returns a variables/arrays to a C++ code. I though I'd include it here in case it is useful to others.

Passing and returning an integer

The C++ code for a function which takes an integer and adds one to the returned value,

extern "C" int add_one(int i)
{
    return i+1;
}

Saved as file test.cpp, note the required extern "C" (this can be removed for C code). This is compiled using g++, with arguments similar to Chinmay Kanchi answer,

g++ -shared -o testlib.so -fPIC test.cpp

The Python code uses load_library from the numpy.ctypeslib assuming the path to the shared library in the same directory as the Python script,

import numpy.ctypeslib as ctl
import ctypes

libname = 'testlib.so'
libdir = './'
lib=ctl.load_library(libname, libdir)

py_add_one = lib.add_one
py_add_one.argtypes = [ctypes.c_int]
value = 5
results = py_add_one(value)
print(results)

This prints 6 as expected.

Passing and printing an array

You can also pass arrays as follows, for a C code to print the element of an array,

extern "C" void print_array(double* array, int N)
{
    for (int i=0; i<N; i++) 
        cout << i << " " << array[i] << endl;
}

which is compiled as before and the imported in the same way. The extra Python code to use this function would then be,

import numpy as np

py_print_array = lib.print_array
py_print_array.argtypes = [ctl.ndpointer(np.float64, 
                                         flags='aligned, c_contiguous'), 
                           ctypes.c_int]
A = np.array([1.4,2.6,3.0], dtype=np.float64)
py_print_array(A, 3)

where we specify the array, the first argument to print_array, as a pointer to a Numpy array of aligned, c_contiguous 64 bit floats and the second argument as an integer which tells the C code the number of elements in the Numpy array. This then printed by the C code as follows,

1.4
2.6
3.0
🌐
Python
svn.python.org › projects › ctypes › trunk › ctypes › docs › manual › tutorial.html
ctypes tutorial
None is passed as a C NULL pointer, byte strings and unicode strings are passed as pointer to the memory block that contains their data (char * or wchar_t *). Python integers and Python longs are passed as the platforms default C int type, their value is masked to fit into the C type. Before we move on calling functions with other parameter types, we have to learn more about ctypes data types.
🌐
PyPI
pypi.org › project › ctypes
ctypes · PyPI
May 15, 2007 - ctypes is a Python package to create and manipulate C data types in Python, and to call functions in dynamic link libraries/shared dlls.
      » pip install ctypes
    
Published   May 15, 2007
Version   1.0.2
🌐
W3Schools
w3schools.com › python › ref_module_ctypes.asp
Python ctypes Module
Python Examples Python Compiler ... Certificate Python Training ... The ctypes module provides C compatible data types and allows calling functions in DLLs/shared libraries....
🌐
Turing
turing.com › kb › ctypes-modules-and-their-implementation-in-python
Ctypes Modules and their implementation in Python.
Ctypes modules are foreign function libraries that provide C-compatible data types and allow the calling functions in shared libraries or dynamic link libraries. In a foreign function library, the Python code will call C functions using only ...
🌐
Readthedocs
scipy-cookbook.readthedocs.io › items › Ctypes.html
Ctypes — SciPy Cookbook documentation - Read the Docs
May 5, 2006 - It is included in the standard library for Python 2.5. ctypes allows to call functions exposed from DLLs/shared libraries and has extensive facilities to create, access and manipulate simple and complicated C data types in Python - in other words: wrap libraries in pure Python.
🌐
Fz-juelich
pgi-jcns.fz-juelich.de › portal › pages › using-c-from-python.html
Using C from Python: How to create a ctypes wrapper - Scientific IT-Systems
ctypes uses a library that creates functions which follow the platform-dependent calling convention during runtime. Thanks to that, it is also possible to wrap a Python function in a way that it becomes callable from C. When dealing with APIs that include events (e.g.
Find elsewhere
🌐
GitHub
github.com › alonho › course › blob › master › doc › ctypes.md
course/doc/ctypes.md at master · alonho/course
It also automatically converts Python's int into signed long int C type. In order to be explicit about your arguments' types use c_* type system: ctypes type | C type | Python type -------------------------------------------------------------------- c_bool | _Bool | bool (1) c_char | char | 1-character string c_wchar | wchar_t | 1-character unicode string c_byte | char | int/long c_ubyte | unsigned char | int/long c_short | short | int/long c_ushort | unsigned short | int/long c_int | int | int/long c_uint | unsigned int | int/long c_long | long | int/long c_ulong | unsigned long | int/long c_longlong | long long | int/long c_ulonglong | unsigned long long | int/long c_float | float | float c_double | double | float c_longdouble | long double | float c_char_p | char * | string or None c_wchar_p | wchar_t * | unicode or None c_void_p | void * | int/long or None
Author   alonho
🌐
Python
docs.python.org › 3.9 › library › ctypes.html
ctypes — A foreign function library for Python — Python 3.9.24 documentation
This document is for an old version of Python that is no longer supported. You should upgrade, and read the Python documentation for the current stable release. ... ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or ...
🌐
Python
wiki.python.org › moin › ctypes
ctypes - Python Wiki
class MaxByteString(ctypes.Structure): _fields_ = [('bytes', 0xFF * ctypes.c_ubyte)] ... That example of an offsetof method works when self is an instance of the structure, the field is a member of self, and the field is an instance of an array class or structure class. The offsetof macro of C works more often. The C macro works for any type of field and works when you have the class but no instance. Imitating the C macro with Python ctypes is possible but tedious: you begin by fetching the _pack_ of the self.__class__ and the ctypes.sizeof for each of the _fields_.
🌐
CodersLegacy
coderslegacy.com › home › python › python ctypes tutorial
Python ctypes Tutorial - CodersLegacy
October 27, 2022 - In this Python Tutorial, we will be discussing the ctypes library. The ctypes library allows us to use functions from the C language which...
🌐
Python
docs.python.org › 3.10 › library › ctypes.html
ctypes — A foreign function library for Python — Python 3.10.19 documentation
None is passed as a C NULL pointer, bytes objects and strings are passed as pointer to the memory block that contains their data (char* or wchar_t*). Python integers are passed as the platforms default C int type, their value is masked to fit into the C type. Before we move on calling functions with other parameter types, we have to learn more about ctypes data types.
🌐
GitHub
github.com › python › cpython › blob › main › Modules › _ctypes › _ctypes.c
cpython/Modules/_ctypes/_ctypes.c at main · python/cpython
Convert a Python object into a function call parameter. ... _validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags, PyObject *argtypes);
Author   python
🌐
Python
svn.python.org › projects › ctypes › branches › ctypes-1.1 › docs › manual › reference.html
ctypes reference
It can be used to wrap these libraries in pure Python. ... When programming in a compiled language, shared libraries are accessed when compiling/linking a program, and when the program is run. The purpose of the find_library function is to locate a library in a way similar to what the compiler does (on platforms with several versions of a shared library the most recent should be loaded), while the ctypes library loaders act like when a program is run, and call the runtime loader directly.
🌐
Medium
medium.com › @datasciencefilmmaker › my-god-its-full-of-stars-2-d75d01d2cb94
My God, It’s Full of Stars (2/7) — Accessing C Structures in Python Using Ctypes | by Data Science Filmmaker | Medium
January 18, 2024 - It makes extensive use of structures and pointers to make accessing memory more efficient than the equivalent object-oriented version, and way more efficient than the Python equivalent would be. I wanted to take advantage of the speed of C while still using mostly Python syntax. Enter the “ctypes” library.
🌐
SageMath
doc.sagemath.org › html › en › thematic_tutorials › numerical_sage › ctypes.html
Ctypes - Thematic Tutorials
Ctypes is a very interesting python package which lets you import shared object libraries into python and call them directly. I should say that even though this is called ctypes, it can be used just as well to call functions from libraries written in fortran.
🌐
Scaler
scaler.com › home › topics › python ctypes module
Python Ctypes Module - Scaler Topics
May 4, 2023 - Using Ctypes data types, you can return a string from the char pointer using a Python native object. ... It is important to understand that char pointers do not work with mutable memory, but with immutable memory. It will be mapped to a newly allocated memory location when a new value is assigned to it. Functions expecting mutable memory might encounter problems because of this. ... In the output above, you can see that each assignment results in a different address. Create string buffers using Ctypes to resolve this issue.
🌐
Dalkescientific
dalkescientific.com › writings › NBN › ctypes.html
ctypes
Ctypes lets you define your own data structures using the same physical layout as C does. You can use Python to build the data structure and pass the result into a C function. Even if you don't want to call a C function you might do this to save memory as Python data structures take somewhat ...