I am coding on a project where I need to process many tree-like data elements, to overcome some performance issues I want to call a given processing function already written in C with the signature int process(Node* root)
and a tree node defined as:
typedef struct Node {
int value;
struct Node ** children;
int num_children;
} Node;
Thus a tree node can have an arbitrary number of child nodes. Analogously a tree node in my Python project is defined as:
class Node():
def __init__(self,value):
self.value = value
self.children = list()
def add_child(self,child):
self.children.append(child)
To call the C function I would like to use CFFI. The problem I ran into is that I need to convert my Python tree data structure to a matching C representation. A node representation, which can be passed to the CFFI function can be created via:
ffi_node = ffi.new("Node *")
ffi_node.value = some_value
But I could not find a way to convert the list references to children to the struct Node** children
.
The type struct node **
in C is almost equivalent to struct node *[]
, which stands for "an array of pointers to nodes". So you want array = ffi.new("struct node *[]", x)
. This allocates an array of length x
, if it is an integer; or, you can directly put in x
a list of the cffi pointers, e.g. array = ffi.new("struct node *[]", [child.as_cffi_pointer() for child in self.children])
.
Be careful that all cffi objects created with ffi.new()
must be kept alive manually as long as needed. Just storing the C pointer somewhere will not keep alive the cffi object in Python. If you forget to keep alive the Python-side cffi object, then the C pointer will quickly point to deallocated memory. This concerns both the ffi.new("struct node *")
and the ffi.new("struct node *[]", x)
.