1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#![feature(specialization)]

//! Rust bindings to the Python interpreter.
//!
//! # Ownership and Lifetimes
//! In Python, all objects are implicitly reference counted.
//! In rust, we will use the `PyObject` type to represent a reference to a Python object.
//!
//! Because all Python objects potentially have multiple owners, the
//! concept of Rust mutability does not apply to Python objects.
//! As a result, this API will allow mutating Python objects even if they are not stored
//! in a mutable Rust variable.
//!
//! The Python interpreter uses a global interpreter lock (GIL)
//! to ensure thread-safety.
//! This API uses a zero-sized `struct Python<'p>` as a token to indicate
//! that a function can assume that the GIL is held.
//!
//! You obtain a `Python` instance by acquiring the GIL,
//! and have to pass it into all operations that call into the Python runtime.
//!
//! # Error Handling
//! The vast majority of operations in this library will return `PyResult<...>`.
//! This is an alias for the type `Result<..., PyErr>`.
//!
//! A `PyErr` represents a Python exception. Errors within the `PyO3` library are
//! also exposed as Python exceptions.
//!
//! # Example
//!
//! ```rust
//! #![feature(specialization)]
//!
//! extern crate pyo3;
//!
//! use pyo3::prelude::*;
//! use pyo3::types::PyDict;
//!
//! fn main() -> PyResult<()> {
//!     let gil = Python::acquire_gil();
//!     let py = gil.python();
//!     let sys = py.import("sys")?;
//!     let version: String = sys.get("version")?.extract()?;
//!
//!     let locals = PyDict::new(py);
//!     locals.set_item("os", py.import("os")?)?;
//!     let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'";
//!     let user: String = py.eval(code, None, Some(&locals))?.extract()?;
//!
//!     println!("Hello {}, I'm Python {}", user, version);
//!     Ok(())
//! }
//! ```
//!
//! # Python extension
//!
//! To allow Python to load the rust code as a Python extension
//! module, you need an initialization function with `Fn(Python, &PyModule) -> PyResult<()>`
//! that is annotates with `#[pymodinit]`. By default the function name will become the module name,
//! but you can override that with `#[pymodinit(name)]`.
//!
//! To creates a Python callable object that invokes a Rust function, specify rust
//! function and decorate it with `#[pyfn()]` attribute. `pyfn()` accepts three parameters.
//!
//! 1. `m`: The module name.
//! 2. name of function visible to Python code.
//! 3. comma separated arguments, i.e. param="None", "*", param3="55"
//!
//!
//! # Example
//!
//! ```rust
//! #![feature(specialization)]
//!
//! extern crate pyo3;
//! use pyo3::prelude::*;
//!
//! // Add bindings to the generated python module
//! // N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
//! /// This module is implemented in Rust.
//! #[pymodinit]
//! fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
//!
//!     #[pyfn(m, "sum_as_string")]
//!     // ``#[pyfn()]` converts the arguments from Python objects to Rust values
//!     // and the Rust return value back into a Python object.
//!     fn sum_as_string_py(a:i64, b:i64) -> PyResult<String> {
//!        let out = sum_as_string(a, b);
//!        Ok(out)
//!     }
//!
//!     Ok(())
//! }
//!
//! // The logic can be implemented as a normal rust function
//! fn sum_as_string(a:i64, b:i64) -> String {
//!     format!("{}", a + b).to_string()
//! }
//!
//! # fn main() {}
//! ```
//!
//! In your `Cargo.toml`, use the `extension-module` feature for the `pyo3` dependency:
//!
//! ```cargo
//! [dependencies.pyo3]
//! version = "*"
//! features = ["extension-module"]
//! ```
//!
//! On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
//!
//! ```toml
//! [target.x86_64-apple-darwin]
//! rustflags = [
//!   "-C", "link-arg=-undefined",
//!   "-C", "link-arg=dynamic_lookup",
//! ]
//! ```
//!
//! Also on macOS, you will need to rename the output from \*.dylib to \*.so. On Windows, you will need to rename the output from \*.dll to \*.pyd.
//!
//! [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) can be used to generate a python package and includes the commands above by default. See [examples/word-count](examples/word-count) and the associated setup.py.

#[cfg(test)]
#[macro_use]
extern crate assert_approx_eq;
#[cfg(test)]
#[macro_use]
extern crate indoc;
// We need those types in the macro exports
#[doc(hidden)]
pub extern crate libc;
// We need that reexport for wrap_function
#[doc(hidden)]
pub extern crate mashup;
extern crate pyo3cls;
extern crate spin;

pub use crate::class::*;
pub use crate::conversion::{
    FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, PyTryInto, ReturnTypeIntoPyResult,
    ToBorrowedObject, ToPyObject,
};
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
pub use crate::instance::{AsPyRef, Py, PyNativeType, PyObjectWithToken, PyToken};
pub use crate::noargs::NoArgs;
pub use crate::object::PyObject;
pub use crate::objectprotocol::ObjectProtocol;
pub use crate::python::{IntoPyPointer, Python, ToPyPointer};
pub use crate::pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GILPool};
pub use crate::typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub use crate::types::exceptions;

/// Rust FFI declarations for Python
pub mod ffi;

#[cfg(not(Py_3))]
mod ffi2;

#[cfg(Py_3)]
mod ffi3;

pub mod class;

/// Constructs a `&'static CStr` literal.
macro_rules! cstr {
    ($s: tt) => {
        // TODO: verify that $s is a string literal without nuls
        unsafe { ::std::ffi::CStr::from_ptr(concat!($s, "\0").as_ptr() as *const _) }
    };
}

pub mod buffer;
#[doc(hidden)]
pub mod callback;
mod conversion;
#[doc(hidden)]
pub mod derive_utils;
mod err;
pub mod freelist;
mod instance;
mod noargs;
mod object;
mod objectprotocol;
pub mod prelude;
pub mod python;
mod pythonrun;
pub mod typeob;
pub mod types;

/// The proc macros, which are also part of the prelude
pub mod proc_macro {
    #[cfg(not(Py_3))]
    pub use pyo3cls::mod2init as pymodinit;
    #[cfg(Py_3)]
    pub use pyo3cls::mod3init as pymodinit;
    /// The proc macro attributes
    pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto};
}

/// Returns a function that takes a [Python] instance and returns a python function.
///
/// Use this together with `#[function]` and [types::PyModule::add_function].
#[macro_export]
macro_rules! wrap_function {
    ($function_name:ident) => {{
        // Get the mashup macro and its helpers into scope
        use $crate::mashup::*;

        mashup! {
            // Make sure this ident matches the one in function_wrapper_ident
            m["method"] = __pyo3_get_function_ $function_name;
        }

        m! {
            &"method"
        }
    }};
}