pyo3_ffi/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
2//! Raw FFI declarations for Python's C API.
3//!
4//! PyO3 can be used to write native Python modules or run Python code and modules from Rust.
5//!
6//! This crate just provides low level bindings to the Python interpreter.
7//! It is meant for advanced users only - regular PyO3 users shouldn't
8//! need to interact with this crate at all.
9//!
10//! The contents of this crate are not documented here, as it would entail
11//! basically copying the documentation from CPython. Consult the [Python/C API Reference
12//! Manual][capi] for up-to-date documentation.
13//!
14//! # Safety
15//!
16//! The functions in this crate lack individual safety documentation, but
17//! generally the following apply:
18//! - Pointer arguments have to point to a valid Python object of the correct type,
19//! although null pointers are sometimes valid input.
20//! - The vast majority can only be used safely while the GIL is held.
21//! - Some functions have additional safety requirements, consult the
22//! [Python/C API Reference Manual][capi]
23//! for more information.
24//!
25//!
26//! # Feature flags
27//!
28//! PyO3 uses [feature flags] to enable you to opt-in to additional functionality. For a detailed
29//! description, see the [Features chapter of the guide].
30//!
31//! ## Optional feature flags
32//!
33//! The following features customize PyO3's behavior:
34//!
35//! - `abi3`: Restricts PyO3's API to a subset of the full Python API which is guaranteed by
36//! [PEP 384] to be forward-compatible with future Python versions.
37//! - `extension-module`: This will tell the linker to keep the Python symbols unresolved, so that
38//! your module can also be used with statically linked Python interpreters. Use this feature when
39//! building an extension module.
40//!
41//! ## `rustc` environment flags
42//!
43//! PyO3 uses `rustc`'s `--cfg` flags to enable or disable code used for different Python versions.
44//! If you want to do this for your own crate, you can do so with the [`pyo3-build-config`] crate.
45//!
46//! - `Py_3_7`, `Py_3_8`, `Py_3_9`, `Py_3_10`, `Py_3_11`, `Py_3_12`, `Py_3_13`: Marks code that is
47//!    only enabled when compiling for a given minimum Python version.
48//! - `Py_LIMITED_API`: Marks code enabled when the `abi3` feature flag is enabled.
49//! - `Py_GIL_DISABLED`: Marks code that runs only in the free-threaded build of CPython.
50//! - `PyPy` - Marks code enabled when compiling for PyPy.
51//! - `GraalPy` - Marks code enabled when compiling for GraalPy.
52//!
53//! Additionally, you can query for the values `Py_DEBUG`, `Py_REF_DEBUG`,
54//! `Py_TRACE_REFS`, and `COUNT_ALLOCS` from `py_sys_config` to query for the
55//! corresponding C build-time defines. For example, to conditionally define
56//! debug code using `Py_DEBUG`, you could do:
57//!
58//! ```rust,ignore
59//! #[cfg(py_sys_config = "Py_DEBUG")]
60//! println!("only runs if python was compiled with Py_DEBUG")
61//! ```
62//!
63//! To use these attributes, add [`pyo3-build-config`] as a build dependency in
64//! your `Cargo.toml`:
65//!
66//! ```toml
67//! [build-dependencies]
68#![doc = concat!("pyo3-build-config =\"", env!("CARGO_PKG_VERSION"),  "\"")]
69//! ```
70//!
71//! And then either create a new `build.rs` file in the project root or modify
72//! the existing `build.rs` file to call `use_pyo3_cfgs()`:
73//!
74//! ```rust,ignore
75//! fn main() {
76//!     pyo3_build_config::use_pyo3_cfgs();
77//! }
78//! ```
79//!
80//! # Minimum supported Rust and Python versions
81//!
82//! `pyo3-ffi` supports the following Python distributions:
83//!   - CPython 3.7 or greater
84//!   - PyPy 7.3 (Python 3.9+)
85//!   - GraalPy 24.0 or greater (Python 3.10+)
86//!
87//! # Example: Building Python Native modules
88//!
89//! PyO3 can be used to generate a native Python module. The easiest way to try this out for the
90//! first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based
91//! Python packages with minimal configuration. The following steps set up some files for an example
92//! Python module, install `maturin`, and then show how to build and import the Python module.
93//!
94//! First, create a new folder (let's call it `string_sum`) containing the following two files:
95//!
96//! **`Cargo.toml`**
97//!
98//! ```toml
99//! [lib]
100//! name = "string_sum"
101//! # "cdylib" is necessary to produce a shared library for Python to import from.
102//! #
103//! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
104//! # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
105//! # crate-type = ["cdylib", "rlib"]
106//! crate-type = ["cdylib"]
107//!
108//! [dependencies.pyo3-ffi]
109#![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"),  "\"")]
110//! features = ["extension-module"]
111//!
112//! [build-dependencies]
113//! # This is only necessary if you need to configure your build based on
114//! # the Python version or the compile-time configuration for the interpreter.
115#![doc = concat!("pyo3_build_config = \"", env!("CARGO_PKG_VERSION"),  "\"")]
116//! ```
117//!
118//! If you need to use conditional compilation based on Python version or how
119//! Python was compiled, you need to add `pyo3-build-config` as a
120//! `build-dependency` in your `Cargo.toml` as in the example above and either
121//! create a new `build.rs` file or modify an existing one so that
122//! `pyo3_build_config::use_pyo3_cfgs()` gets called at build time:
123//!
124//! **`build.rs`**
125//! ```rust,ignore
126//! fn main() {
127//!     pyo3_build_config::use_pyo3_cfgs()
128//! }
129//! ```
130//!
131//! **`src/lib.rs`**
132//! ```rust
133//! use std::os::raw::{c_char, c_long};
134//! use std::ptr;
135//!
136//! use pyo3_ffi::*;
137//!
138//! static mut MODULE_DEF: PyModuleDef = PyModuleDef {
139//!     m_base: PyModuleDef_HEAD_INIT,
140//!     m_name: c_str!("string_sum").as_ptr(),
141//!     m_doc: c_str!("A Python module written in Rust.").as_ptr(),
142//!     m_size: 0,
143//!     m_methods: unsafe { METHODS as *const [PyMethodDef] as *mut PyMethodDef },
144//!     m_slots: std::ptr::null_mut(),
145//!     m_traverse: None,
146//!     m_clear: None,
147//!     m_free: None,
148//! };
149//!
150//! static mut METHODS: &[PyMethodDef] = &[
151//!     PyMethodDef {
152//!         ml_name: c_str!("sum_as_string").as_ptr(),
153//!         ml_meth: PyMethodDefPointer {
154//!             PyCFunctionFast: sum_as_string,
155//!         },
156//!         ml_flags: METH_FASTCALL,
157//!         ml_doc: c_str!("returns the sum of two integers as a string").as_ptr(),
158//!     },
159//!     // A zeroed PyMethodDef to mark the end of the array.
160//!     PyMethodDef::zeroed(),
161//! ];
162//!
163//! // The module initialization function, which must be named `PyInit_<your_module>`.
164//! #[allow(non_snake_case)]
165//! #[no_mangle]
166//! pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject {
167//!     let module = PyModule_Create(ptr::addr_of_mut!(MODULE_DEF));
168//!     if module.is_null() {
169//!         return module;
170//!     }
171//!     #[cfg(Py_GIL_DISABLED)]
172//!     {
173//!         if PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED) < 0 {
174//!             Py_DECREF(module);
175//!             return std::ptr::null_mut();
176//!         }
177//!     }
178//!     module
179//! }
180//!
181//! /// A helper to parse function arguments
182//! /// If we used PyO3's proc macros they'd handle all of this boilerplate for us :)
183//! unsafe fn parse_arg_as_i32(obj: *mut PyObject, n_arg: usize) -> Option<i32> {
184//!     if PyLong_Check(obj) == 0 {
185//!         let msg = format!(
186//!             "sum_as_string expected an int for positional argument {}\0",
187//!             n_arg
188//!         );
189//!         PyErr_SetString(PyExc_TypeError, msg.as_ptr().cast::<c_char>());
190//!         return None;
191//!     }
192//!
193//!     // Let's keep the behaviour consistent on platforms where `c_long` is bigger than 32 bits.
194//!     // In particular, it is an i32 on Windows but i64 on most Linux systems
195//!     let mut overflow = 0;
196//!     let i_long: c_long = PyLong_AsLongAndOverflow(obj, &mut overflow);
197//!
198//!     #[allow(irrefutable_let_patterns)] // some platforms have c_long equal to i32
199//!     if overflow != 0 {
200//!         raise_overflowerror(obj);
201//!         None
202//!     } else if let Ok(i) = i_long.try_into() {
203//!         Some(i)
204//!     } else {
205//!         raise_overflowerror(obj);
206//!         None
207//!     }
208//! }
209//!
210//! unsafe fn raise_overflowerror(obj: *mut PyObject) {
211//!     let obj_repr = PyObject_Str(obj);
212//!     if !obj_repr.is_null() {
213//!         let mut size = 0;
214//!         let p = PyUnicode_AsUTF8AndSize(obj_repr, &mut size);
215//!         if !p.is_null() {
216//!             let s = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
217//!                 p.cast::<u8>(),
218//!                 size as usize,
219//!             ));
220//!             let msg = format!("cannot fit {} in 32 bits\0", s);
221//!
222//!             PyErr_SetString(PyExc_OverflowError, msg.as_ptr().cast::<c_char>());
223//!         }
224//!         Py_DECREF(obj_repr);
225//!     }
226//! }
227//!
228//! pub unsafe extern "C" fn sum_as_string(
229//!     _self: *mut PyObject,
230//!     args: *mut *mut PyObject,
231//!     nargs: Py_ssize_t,
232//! ) -> *mut PyObject {
233//!     if nargs != 2 {
234//!         PyErr_SetString(
235//!             PyExc_TypeError,
236//!             c_str!("sum_as_string expected 2 positional arguments").as_ptr(),
237//!         );
238//!         return std::ptr::null_mut();
239//!     }
240//!
241//!     let (first, second) = (*args, *args.add(1));
242//!
243//!     let first = match parse_arg_as_i32(first, 1) {
244//!         Some(x) => x,
245//!         None => return std::ptr::null_mut(),
246//!     };
247//!     let second = match parse_arg_as_i32(second, 2) {
248//!         Some(x) => x,
249//!         None => return std::ptr::null_mut(),
250//!     };
251//!
252//!     match first.checked_add(second) {
253//!         Some(sum) => {
254//!             let string = sum.to_string();
255//!             PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as isize)
256//!         }
257//!         None => {
258//!             PyErr_SetString(
259//!                 PyExc_OverflowError,
260//!                 c_str!("arguments too large to add").as_ptr(),
261//!             );
262//!             std::ptr::null_mut()
263//!         }
264//!     }
265//! }
266//! ```
267//!
268//! With those two files in place, now `maturin` needs to be installed. This can be done using
269//! Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin`
270//! into it:
271//! ```bash
272//! $ cd string_sum
273//! $ python -m venv .env
274//! $ source .env/bin/activate
275//! $ pip install maturin
276//! ```
277//!
278//! Now build and execute the module:
279//! ```bash
280//! $ maturin develop
281//! # lots of progress output as maturin runs the compilation...
282//! $ python
283//! >>> import string_sum
284//! >>> string_sum.sum_as_string(5, 20)
285//! '25'
286//! ```
287//!
288//! As well as with `maturin`, it is possible to build using [setuptools-rust] or
289//! [manually][manual_builds]. Both offer more flexibility than `maturin` but require further
290//! configuration.
291//!
292//! This example stores the module definition statically and uses the `PyModule_Create` function
293//! in the CPython C API to register the module. This is the "old" style for registering modules
294//! and has the limitation that it cannot support subinterpreters. You can also create a module
295//! using the new multi-phase initialization API that does support subinterpreters. See the
296//! `sequential` project located in the `examples` directory at the root of the `pyo3-ffi` crate
297//! for a worked example of how to this using `pyo3-ffi`.
298//!
299//! # Using Python from Rust
300//!
301//! To embed Python into a Rust binary, you need to ensure that your Python installation contains a
302//! shared library. The following steps demonstrate how to ensure this (for Ubuntu).
303//!
304//! To install the Python shared library on Ubuntu:
305//! ```bash
306//! sudo apt install python3-dev
307//! ```
308//!
309//! While most projects use the safe wrapper provided by pyo3,
310//! you can take a look at the [`orjson`] library as an example on how to use `pyo3-ffi` directly.
311//! For those well versed in C and Rust the [tutorials] from the CPython documentation
312//! can be easily converted to rust as well.
313//!
314//! [tutorials]: https://docs.python.org/3/extending/
315//! [`orjson`]: https://github.com/ijl/orjson
316//! [capi]: https://docs.python.org/3/c-api/index.html
317//! [`maturin`]: https://github.com/PyO3/maturin "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages"
318//! [`pyo3-build-config`]: https://docs.rs/pyo3-build-config
319//! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html "Features - The Cargo Book"
320#![doc = concat!("[manual_builds]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution.html#manual-builds \"Manual builds - Building and Distribution - PyO3 user guide\"")]
321//! [setuptools-rust]: https://github.com/PyO3/setuptools-rust "Setuptools plugin for Rust extensions"
322//! [PEP 384]: https://www.python.org/dev/peps/pep-0384 "PEP 384 -- Defining a Stable ABI"
323#![doc = concat!("[Features chapter of the guide]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/features.html#features-reference \"Features eference - PyO3 user guide\"")]
324#![allow(
325    missing_docs,
326    non_camel_case_types,
327    non_snake_case,
328    non_upper_case_globals,
329    clippy::upper_case_acronyms,
330    clippy::missing_safety_doc
331)]
332#![warn(elided_lifetimes_in_paths, unused_lifetimes)]
333
334// Until `extern type` is stabilized, use the recommended approach to
335// model opaque types:
336// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
337macro_rules! opaque_struct {
338    ($name:ident) => {
339        #[repr(C)]
340        pub struct $name([u8; 0]);
341    };
342}
343
344/// This is a helper macro to create a `&'static CStr`.
345///
346/// It can be used on all Rust versions supported by PyO3, unlike c"" literals which
347/// were stabilised in Rust 1.77.
348///
349/// Due to the nature of PyO3 making heavy use of C FFI interop with Python, it is
350/// common for PyO3 to use CStr.
351///
352/// Examples:
353///
354/// ```rust
355/// use std::ffi::CStr;
356///
357/// const HELLO: &CStr = pyo3_ffi::c_str!("hello");
358/// static WORLD: &CStr = pyo3_ffi::c_str!("world");
359/// ```
360#[macro_export]
361macro_rules! c_str {
362    ($s:expr) => {
363        $crate::_cstr_from_utf8_with_nul_checked(concat!($s, "\0"))
364    };
365}
366
367/// Private helper for `c_str!` macro.
368#[doc(hidden)]
369pub const fn _cstr_from_utf8_with_nul_checked(s: &str) -> &CStr {
370    // TODO: Replace this implementation with `CStr::from_bytes_with_nul` when MSRV above 1.72.
371    let bytes = s.as_bytes();
372    let len = bytes.len();
373    assert!(
374        !bytes.is_empty() && bytes[bytes.len() - 1] == b'\0',
375        "string is not nul-terminated"
376    );
377    let mut i = 0;
378    let non_null_len = len - 1;
379    while i < non_null_len {
380        assert!(bytes[i] != b'\0', "string contains null bytes");
381        i += 1;
382    }
383
384    unsafe { CStr::from_bytes_with_nul_unchecked(bytes) }
385}
386
387use std::ffi::CStr;
388
389pub mod compat;
390mod impl_;
391
392pub use self::abstract_::*;
393pub use self::bltinmodule::*;
394pub use self::boolobject::*;
395pub use self::bytearrayobject::*;
396pub use self::bytesobject::*;
397pub use self::ceval::*;
398#[cfg(Py_LIMITED_API)]
399pub use self::code::*;
400pub use self::codecs::*;
401pub use self::compile::*;
402pub use self::complexobject::*;
403#[cfg(all(Py_3_8, not(Py_LIMITED_API)))]
404pub use self::context::*;
405#[cfg(not(Py_LIMITED_API))]
406pub use self::datetime::*;
407pub use self::descrobject::*;
408pub use self::dictobject::*;
409pub use self::enumobject::*;
410pub use self::fileobject::*;
411pub use self::fileutils::*;
412pub use self::floatobject::*;
413pub use self::import::*;
414pub use self::intrcheck::*;
415pub use self::iterobject::*;
416pub use self::listobject::*;
417pub use self::longobject::*;
418#[cfg(not(Py_LIMITED_API))]
419pub use self::marshal::*;
420pub use self::memoryobject::*;
421pub use self::methodobject::*;
422pub use self::modsupport::*;
423pub use self::moduleobject::*;
424pub use self::object::*;
425pub use self::objimpl::*;
426pub use self::osmodule::*;
427#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]
428pub use self::pyarena::*;
429#[cfg(Py_3_11)]
430pub use self::pybuffer::*;
431pub use self::pycapsule::*;
432pub use self::pyerrors::*;
433pub use self::pyframe::*;
434pub use self::pyhash::*;
435pub use self::pylifecycle::*;
436pub use self::pymem::*;
437pub use self::pyport::*;
438pub use self::pystate::*;
439pub use self::pystrtod::*;
440pub use self::pythonrun::*;
441pub use self::rangeobject::*;
442pub use self::setobject::*;
443pub use self::sliceobject::*;
444pub use self::structseq::*;
445pub use self::sysmodule::*;
446pub use self::traceback::*;
447pub use self::tupleobject::*;
448pub use self::typeslots::*;
449pub use self::unicodeobject::*;
450pub use self::warnings::*;
451pub use self::weakrefobject::*;
452
453mod abstract_;
454// skipped asdl.h
455// skipped ast.h
456mod bltinmodule;
457mod boolobject;
458mod bytearrayobject;
459mod bytesobject;
460// skipped cellobject.h
461mod ceval;
462// skipped classobject.h
463#[cfg(Py_LIMITED_API)]
464mod code;
465mod codecs;
466mod compile;
467mod complexobject;
468#[cfg(all(Py_3_8, not(Py_LIMITED_API)))]
469mod context; // It's actually 3.7.1, but no cfg for patches.
470#[cfg(not(Py_LIMITED_API))]
471pub(crate) mod datetime;
472mod descrobject;
473mod dictobject;
474// skipped dynamic_annotations.h
475mod enumobject;
476// skipped errcode.h
477// skipped exports.h
478mod fileobject;
479mod fileutils;
480mod floatobject;
481// skipped empty frameobject.h
482// skipped genericaliasobject.h
483mod import;
484// skipped interpreteridobject.h
485mod intrcheck;
486mod iterobject;
487mod listobject;
488// skipped longintrepr.h
489mod longobject;
490#[cfg(not(Py_LIMITED_API))]
491pub mod marshal;
492mod memoryobject;
493mod methodobject;
494mod modsupport;
495mod moduleobject;
496// skipped namespaceobject.h
497mod object;
498mod objimpl;
499// skipped odictobject.h
500// skipped opcode.h
501// skipped osdefs.h
502mod osmodule;
503// skipped parser_interface.h
504// skipped patchlevel.h
505// skipped picklebufobject.h
506// skipped pyctype.h
507// skipped py_curses.h
508#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]
509mod pyarena;
510#[cfg(Py_3_11)]
511mod pybuffer;
512mod pycapsule;
513// skipped pydtrace.h
514mod pyerrors;
515// skipped pyexpat.h
516// skipped pyfpe.h
517mod pyframe;
518mod pyhash;
519mod pylifecycle;
520// skipped pymacconfig.h
521// skipped pymacro.h
522// skipped pymath.h
523mod pymem;
524mod pyport;
525mod pystate;
526// skipped pystats.h
527mod pythonrun;
528// skipped pystrhex.h
529// skipped pystrcmp.h
530mod pystrtod;
531// skipped pythread.h
532// skipped pytime.h
533mod rangeobject;
534mod setobject;
535mod sliceobject;
536mod structseq;
537mod sysmodule;
538mod traceback;
539// skipped tracemalloc.h
540mod tupleobject;
541mod typeslots;
542mod unicodeobject;
543mod warnings;
544mod weakrefobject;
545
546// Additional headers that are not exported by Python.h
547#[deprecated(note = "Python 3.12")]
548pub mod structmember;
549
550// "Limited API" definitions matching Python's `include/cpython` directory.
551#[cfg(not(Py_LIMITED_API))]
552mod cpython;
553
554#[cfg(not(Py_LIMITED_API))]
555pub use self::cpython::*;