Skip to content

Module definition abstraction #9

@emmatyping

Description

@emmatyping

Python modules rely on a static definition of a module. To avoid needing to have a static, threadsafe PyObject, I propose we use PyModExport, which is the new way of defining modules, and does not rely on the safety of a static, threadsafe PyObject.

An example of a module definition, taken from the above PEP:

static PyModuleDef_Slot examplemodule_slots[] = {
    {Py_mod_name, "examplemodule"},
    {Py_mod_doc, (char*)examplemodule_doc},
    {Py_mod_methods, examplemodule_methods},
    {Py_mod_state_size, (void*)sizeof(examplemodule_state)},
    {Py_mod_exec, (void*)examplemodule_exec},
    {0}
};

PyMODEXPORT_FUNC
PyModExport_examplemodule(void)
{
    return examplemodule_slots;
}

PyMODEXPORT_FUNC is equivalent to *mut PyModuleDef_Slot.

One design I have in mind is something along the lines of:

pub enum PyModuleDefSlot {
    Name(&'static CStr),
    Doc(&'static CStr),
    MultipleInterpreters(*mut c_void),
    GIL(*mut c_void),
    StateSize(usize),
    // ... etc.
}

pub struct PyModuleDef<const N: usize>(UnsafeCell<[ffi::PyModuleDef_Slot; N]>);

impl<const N: usize> PyModuleDef<N> {
    pub const fn new(slots: [PyModuleDefSlot; N]) -> Self {
        todo!()
    }

    pub fn as_mut_ptr(&'static self) -> *mut PyModuleDef_Slot {
        self.0.get() as *mut PyModuleDef_Slot
    }
}

unsafe impl<const N: usize> Sync for PyModuleDef<N> {}

static MODULE: PyModuleDef<5> = PyModule::new([
    PyModuleDefSlot::Name(c"mymodule"),
    PyModuleDefSlot::Doc(c"An example module for a proof of concept"),
    // etc.
]);

#[unsafe(no_mangle)]
unsafe extern "C" fn PyModExport_mymodule() -> *mut PyModuleDef_Slot {
    MODULE.as_mut_ptr()
}

I think this isn't currently sound because we probably need a thread state-aware lock to prevent races on MODULE.as_mut_ptr()?

We will likely also want a design for specifying methods that are part of the module, which are listed in a static array similar to the PyModExport static.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions