-
Notifications
You must be signed in to change notification settings - Fork 953
Closed
Labels
Description
This is a follow-on from the discussion in indygreg/PyOxidizer#324.
The issue mentioned there is that the ffi bindings in initconfig.rs for PyPreConfig and PyConfig are cumbersome to initialize safely, so it would be helpful for us to provide safe wrappers for PyPreConfig_InitPythonConfig etc.
Quoting indygreg/PyOxidizer#324 (comment), a possible design is (credit @wkschwartz)
use std::mem::MaybeUninit;
impl PyPreConfig {
/// Create a new instance initialized with the [Python configuration].
///
/// [Python configuration]: https://docs.python.org/3/c-api/init_config.html#init-python-config
fn python() -> Self {
let mut ppc = MaybeUninit::uninit();
unsafe {
PyPreConfig_InitPythonConfig(ppc.as_mut_ptr());
ppc.assume_init()
}
}
/// Create a new instance initialized with the [isolated configuration].
///
/// [isolated configuration]: https://docs.python.org/3/c-api/init_config.html#isolated-configuration
fn isolated() -> Self {
let mut ppc = MaybeUninit::uninit();
unsafe {
PyPreConfig_InitIsolatedConfig(ppc.as_mut_ptr());
ppc.assume_init()
}
}
}I have a few notes on this design before we commit to this:
- After a user creates one of these FFI as per structs, they will often still need to make use of the unsafe helpers such as
PyConfig_SetBytesStringto further configure the fields contained. Should we also provide safe APIs for these? - We recently split out the
auto-initializefeature, asking users to callprepare_freethreaded_python()directly if they needed. That API doesn't offer a way to tie in these ffi structures. If we are implementing some safe wrappers for the PEP 587 APIs in PyO3, I think it would be nice to go the whole way so that users can have a safe alternative toprepare_freethreaded_python(). - Once done, users should call
PyConfig_Clearto clean up the allocations contained. Sounds like a perfect candidate for animpl Drop.
Points 1 and 3 particular make me think that instead of adding the methods provided above, we could consider adding a module pyo3::init, which contains safe wrappers roughly along the lines of the following:
pub fn initialize_python_from_config(config: &PyConfig) {
unsafe { ffi::Py_InitializeFromConfig(config); }
}
pub struct PyConfig(ffi::PyConfig);
impl PyConfig {
// contains the ::isolated() and ::python() methods above, as well as other safe helpers to set all the fields
}
impl Drop for PyConfig {
fn drop(&mut self) {
unsafe { ffi::PyConfig_Clear(&mut self.0); }
}
}Reactions are currently unavailable