Instead PyO3 [1] lets you "write a native Python module in Rust", and it works great. A much better choice IMO.
Instead PyO3 [1] lets you "write a native Python module in Rust", and it works great. A much better choice IMO.
I've created a library using this crate (https://github.com/wiktor-k/pysequoia/) and most of the time I could just focus on the problem domain instead of technical details of the bindings.
There are just a couple of smaller issues (eg. Python to Rust async is not built in) but overall it's really nice.
I wouldn't necessarily expect a demo; but not mentioning it at all seems like it could lead readers down a path where they choose the "most performant" option presented (FFI + ctypes). The post has a "To go further:" link section where even a quick link to PyO3 would go a long way. So I thought I'd mention the downsides and an alternative on HN.
How to write Python extensions in Rust with PyO3 - https://news.ycombinator.com/item?id=34968186 - Feb 2023 (9 comments)
PyO3 – Python Extensions in Rust - https://news.ycombinator.com/item?id=32247452 - July 2022 (1 comment)
Calling Rust from Python using PyO3 - https://news.ycombinator.com/item?id=29368530 - Nov 2021 (49 comments)
PyO3: Rust Bindings for the Python Interpreter - https://news.ycombinator.com/item?id=25956502 - Jan 2021 (77 comments)
Writing Python Extensions in Rust Using PyO3 - https://news.ycombinator.com/item?id=17423013 - June 2018 (1 comment)
PyO3: Python Rust binding - https://news.ycombinator.com/item?id=14859844 - July 2017 (15 comments)
(First Release) PyO3: a Python-Rust Binding Library - https://news.ycombinator.com/item?id=14846606 - July 2017 (1 comment)
Well it depends. C is the lingua franca of Computer Science. These days I write a lot of code that needs to be accessible to a variety of languages and environments. Python, C#, C++, Matlab, Unity, Unreal, etc.
Write a C API and your code can be used anywhere. Now if you know you only ever need to support Python then sure look into PyO3. But if you have mixed use you can’t be the flexibility of a C API.
The benefit is that you only need to ship the CPython extension, you can build it with cargo, and everything's in one place. I've maintained bindings for Python and C# to native libraries, and it's usually a pain for various reasons.
The C API might be able to be used anywhere, but that doesn't mean it's ergonomic, easy to use, or safe.
Definitely true. That said I think there is an under appreciated beautiy to a clean C API.
It’s easy to “upgrade” a C API with per-language/environment bindings. It can be near impossible to “downgrade” a high-level API to C.
fn string_sum(_py: Python<'_>, m: &PyModule)
is the idea that the `Python` type represents the GIL and you're actually acquiring it from within your Rust application?It's essentially a dummy parameter that serves as proof that the GIL is held. You need to provide it to PyO3 when calling back into the Python runtime, that way the compiler ensures the GIL is still held where required.
Also, there is no ctypes involved, as the result is a CPython extension that just loads on the Python side.
Also no ctypes.
There are also things I am still struggling with. For example, there is a rust function I want to repeatedly call from python, that takes in a large unchanging python array. How can I pass the array from python to rust only once, i.e do the type conversion just once, so I don't have to pay that cost repeatedly.