Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callbacks with ctypes (How to call a python function from C)

Tags:

python

ctypes

Is it possible to call a Python function from a C dll function?

We consider this C function:

 void foo( void (*functionPtr)(int,int) , int a, int b);

On Python, I would like to call foo and set the callback to a Python function:

def callback(a, b):
    print("foo has finished its job (%d, %d)" % (a.value,b.value))

dll.foo( callback, c_int(a), c_int(b) )

Unfortunately, the ctypes documentation is pretty light on this topic and the above code does not work.

like image 984
nowox Avatar asked Nov 02 '15 18:11

nowox


People also ask

How do I call a callback function in Python?

In the Parallel Python Module, the submit function is known as the callback function. The callback function acts as an argument for any other function. The other function in which the callback function is an argument calls the callback function in its function definition.

How are callbacks invoked?

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

Is Ctypes a built in Python?

ctypes is a python built-in library that invokes exported functions from native compiled libraries. Note: Since this library handles compiled code, it is relatively OS dependent.


2 Answers

import ctypes as c

@c.CFUNCTYPE(None, c.c_int, c.c_int)
def callback(a, b):
    print("foo has finished its job (%d, %d)" % (a.value, b.value))

dll.foo(callback, a, b) # assuming a,b are ints

If you need stdcall calling conventions, use WINFUNCTYPE instead.

Note: if foo may store the callback to be called at a later time then make sure that Python callback is alive (it is enough if it is defined at the global level using the decorator as shown in the example -- modules are essentially immortal in Python unless you try to remove them explicitly).

like image 140
jfs Avatar answered Oct 10 '22 17:10

jfs


Use CFUNCTYPE to create a callback type:

c_callback = CFUNCTYPE(None, c_int, c_int)(callback)
dll.foo(c_callback, a, b)
like image 45
nneonneo Avatar answered Oct 10 '22 17:10

nneonneo