In the previous part we have seen how to pass not trivial data to Rust functions such as a Python list. It is still not enough, though. In many cases we need to pass complex data structure back and forth from a Rust library. We may need to pass quaternions, 3D points, trees, a list of “books”… In short: anything.
Learning how to pass custom aggregated data types to Rust libraries (and back to Python) will be the focus of this part!
The Rust Side: Working with Points
As usual, the first thing to do is to implement the Rust library function. This time we need to design first a
struct that will represent our complex object. We chose to represent 2D points.
This is a classic rust
struct declaration, but we need to use
#[repr(C)] to explain to the compiler that
Point is a C struct.
Now, we can simply implement the desired function. In this example we will implement a function that, given two
Point representing a segment,returns the midpoint of the segment.
The Python Side
The Rust side of the problem is quite easy. As you have seen, it is just Rust programming, but with a
#[repr(C)] spice on top of the
Python side is slightly more complicated. Also in Python, we need first to declare the
The class representing our C/Rust struct is different from the usual one.
- The class must extend the
ctypes.Structureclass defined in
- The fields of the C struct must be defined using the builtin
_fields_attribute. This attribute must contain a **list of tuples. **Each tuple must contain the 1) name of the field and 2) the type of the field according the
ctypesdeclaration. In our case
Pointhas two fields, “x” and “y”, both doubles. Now it is time to setup our Rust function. We specify the type declaration for our function.
Then we can use this function as usual!
And we have done. It is not so difficult, isn’t it? Now, mixing up this lesson with the previous one you can easily setup an external Rust function to compute the centroid of a list of
Point. I will leave you this as an exercise (HINT: you may need some POINTER magic).
For now, I think I’ve covered the important topics for this task. You should now be able to combine all this information in order to provide Python interfaces to a huge family of Rust functions (maybe every function you will ever need). If you have any particular use case I’ve not covered or you are interested in, ask me anything! I will be happy to add some other part to this series in order fill the gaps!
Finally, I remind you that all the code of this series is available on GitHub.
Have a nice day!