# Binding Rust Functions to Python Using PyO3 * Status: proposed * Deciders: @ryan-z, @link-verses, @prasaanth-verses, @tom-mason-verses * Date: 2024-03-29 Technical Story: https://verses.atlassian.net/browse/GPDT-47 ## Context and Problem Statement We have three language-specific SDKs (Rust, Node, Python) that provide the same functionality: authentication and operations on Genius DB. While they offer a great developer experience, they also result in duplicate code and potential performance inefficiencies. By binding Rust functions to Python, we can leverage the performance benefits of Rust and reduce code duplication. However, the challenge lies in doing this in a way that is efficient, maintains Rust's safety guarantees, and is easily understandable by Python developers who may not be familiar with Rust. ## Decision Drivers * Performance: The solution must introduce minimal overhead. * Safety: The solution must uphold Rust's safety guarantees. * Maintainability: Preference for solutions with active maintenance and community support. * Developer Experience: The solution should be easily understandable by Python developers without requiring them to learn extensive new technologies. ## Considered Options * PyO3 * rust-cpython * Milksnake * Manual C FFI Bindings ## Decision Outcome Chosen option: "PyO3", because it is actively maintained, specifically designed for creating Python bindings to Rust, and does not require Python developers to understand additional technologies like CFFI. It meets all our key decision drivers: performance, safety, maintainability, and developer experience. ### Positive Consequences * Maintains the high performance of Rust within Python applications. * Ensures the safety features of Rust are not compromised. * Facilitates easier maintenance and updates due to active community support. * Provides a more straightforward integration path for Python developers. ### Negative Consequences * Requires developers to have or gain some knowledge of Rust for effective use. * Limited to the Python ecosystem, which might restrict some Rust features. ## Pros and Cons of the Options ### Option 1: PyO3 PyO3 is a project specifically designed to facilitate the creation of Python bindings for Rust code, offering tools and features that seamlessly bridge the two languages. #### PyO3 is good, because * Actively maintained and widely used in the Rust community. * Directly addresses the need for binding Rust to Python without intermediate layers. * Provides automatic conversions between Rust and Python types. #### PyO3 is bad, because * Pyo3 is only specific to Python; other language SDKs will not be able to reuse these bindings. * Requires Rust knowledge for setup and optimization. * Python developers may need to learn Rust concepts. ### Option 2: rust-cpython rust-cpython is an older project for binding Rust with Python, not actively maintained and recommends PyO3 as an alternative. #### rust-cpython is good, because * Was designed with a similar goal in mind. #### rust-cpython is bad, because * No longer maintained. * Community recommends moving to PyO3. ### Option 3: Milksnake Milksnake is a tool designed to help distribute Python extensions written in Rust as dynamic libraries, using CFFI to interact with Python. #### Milksnake is good, because * Allows Rust code to be packaged as dynamic libraries usable in Python. #### Milksnake is bad, because * Requires understanding of CFFI, adding a learning curve for Python developers. * Not directly focused on Rust-Python bindings but rather on distribution. ### Option 4: Manual C FFI Bindings Manual C FFI Bindings involve directly using the C Foreign Function Interface to integrate Rust code with Python, providing a lower-level approach than the other options. #### Manual C FFI Bindings are good, because * Offer full control over the integration process, potentially optimizing performance. * Do not depend on third-party libraries or tools. * Compatible with other languages that we may support in the future. #### Manual C FFI Bindings are bad, because * Require significant effort and expertise in both Rust and C, as well as understanding Python's C API. * Increase complexity and maintenance overhead. * Riskier in terms of safety if not carefully managed. * ## Links * [Documentation] [PyO3 GitHub Repository](https://github.com/PyO3/pyo3) * [Documentation] [rust-cpython GitHub Repository](https://github.com/dgrunwald/rust-cpython) * [Documentation] [Milksnake GitHub Repository](https://github.com/getsentry/milksnake)