From 4f96ef42f6d3aafdfa0c23530dc6f84cfe9efdf0 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Tue, 6 Aug 2024 18:33:18 +0100 Subject: [PATCH] ffi: update `modsupport.rs` for Python 3.13 --- newsfragments/4420.fixed.md | 1 + newsfragments/4420.removed.md | 1 + pyo3-ffi/src/modsupport.rs | 39 +++++++-------------------------- tests/test_pyfunction.rs | 41 +++++++++++++++++++++-------------- 4 files changed, 35 insertions(+), 47 deletions(-) create mode 100644 newsfragments/4420.fixed.md create mode 100644 newsfragments/4420.removed.md diff --git a/newsfragments/4420.fixed.md b/newsfragments/4420.fixed.md new file mode 100644 index 00000000000..dec974555d9 --- /dev/null +++ b/newsfragments/4420.fixed.md @@ -0,0 +1 @@ +Correct FFI definition `PyArg_ParseTupleAndKeywords` to take `*const *const c_char` instead of `*mut *mut c_char` on Python 3.13 and up. diff --git a/newsfragments/4420.removed.md b/newsfragments/4420.removed.md new file mode 100644 index 00000000000..9d17c33e143 --- /dev/null +++ b/newsfragments/4420.removed.md @@ -0,0 +1 @@ +Remove FFI definition of private variable `_Py_PackageContext`. diff --git a/pyo3-ffi/src/modsupport.rs b/pyo3-ffi/src/modsupport.rs index b259c70059e..4a18d30f97c 100644 --- a/pyo3-ffi/src/modsupport.rs +++ b/pyo3-ffi/src/modsupport.rs @@ -14,9 +14,14 @@ extern "C" { arg1: *mut PyObject, arg2: *mut PyObject, arg3: *const c_char, - arg4: *mut *mut c_char, + #[cfg(not(Py_3_13))] arg4: *mut *mut c_char, + #[cfg(Py_3_13)] arg4: *const *const c_char, ... ) -> c_int; + + // skipped PyArg_VaParse + // skipped PyArg_VaParseTupleAndKeywords + pub fn PyArg_ValidateKeywordArguments(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyArg_UnpackTuple")] pub fn PyArg_UnpackTuple( @@ -26,32 +31,10 @@ extern "C" { arg4: Py_ssize_t, ... ) -> c_int; + #[cfg_attr(PyPy, link_name = "PyPy_BuildValue")] pub fn Py_BuildValue(arg1: *const c_char, ...) -> *mut PyObject; - // #[cfg_attr(PyPy, link_name = "_PyPy_BuildValue_SizeT")] - //pub fn _Py_BuildValue_SizeT(arg1: *const c_char, ...) - // -> *mut PyObject; - // #[cfg_attr(PyPy, link_name = "PyPy_VaBuildValue")] - - // skipped non-limited _PyArg_UnpackStack - // skipped non-limited _PyArg_NoKeywords - // skipped non-limited _PyArg_NoKwnames - // skipped non-limited _PyArg_NoPositional - // skipped non-limited _PyArg_BadArgument - // skipped non-limited _PyArg_CheckPositional - - //pub fn Py_VaBuildValue(arg1: *const c_char, arg2: va_list) - // -> *mut PyObject; - - // skipped non-limited _Py_VaBuildStack - // skipped non-limited _PyArg_Parser - - // skipped non-limited _PyArg_ParseTupleAndKeywordsFast - // skipped non-limited _PyArg_ParseStack - // skipped non-limited _PyArg_ParseStackAndKeywords - // skipped non-limited _PyArg_VaParseTupleAndKeywordsFast - // skipped non-limited _PyArg_UnpackKeywords - // skipped non-limited _PyArg_Fini + // skipped Py_VaBuildValue #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "PyPyModule_AddObjectRef")] @@ -159,9 +142,3 @@ pub unsafe fn PyModule_FromDefAndSpec(def: *mut PyModuleDef, spec: *mut PyObject }, ) } - -#[cfg(not(Py_LIMITED_API))] -#[cfg_attr(windows, link(name = "pythonXY"))] -extern "C" { - pub static mut _Py_PackageContext: *const c_char; -} diff --git a/tests/test_pyfunction.rs b/tests/test_pyfunction.rs index 903db689527..24ef32d6994 100644 --- a/tests/test_pyfunction.rs +++ b/tests/test_pyfunction.rs @@ -363,8 +363,7 @@ fn test_pycfunction_new() { #[test] fn test_pycfunction_new_with_keywords() { use pyo3::ffi; - use std::ffi::CString; - use std::os::raw::{c_char, c_long}; + use std::os::raw::c_long; use std::ptr; Python::with_gil(|py| { @@ -375,28 +374,38 @@ fn test_pycfunction_new_with_keywords() { ) -> *mut ffi::PyObject { let mut foo: c_long = 0; let mut bar: c_long = 0; - let foo_ptr: *mut c_long = &mut foo; - let bar_ptr: *mut c_long = &mut bar; - let foo_name = CString::new("foo").unwrap(); - let foo_name_raw: *mut c_char = foo_name.into_raw(); - let kw_bar_name = CString::new("kw_bar").unwrap(); - let kw_bar_name_raw: *mut c_char = kw_bar_name.into_raw(); + #[cfg(not(Py_3_13))] + let foo_name = std::ffi::CString::new("foo").unwrap(); + #[cfg(not(Py_3_13))] + let kw_bar_name = std::ffi::CString::new("kw_bar").unwrap(); + #[cfg(not(Py_3_13))] + let mut args_names = [foo_name.into_raw(), kw_bar_name.into_raw(), ptr::null_mut()]; - let mut arglist = vec![foo_name_raw, kw_bar_name_raw, ptr::null_mut()]; - let arglist_ptr: *mut *mut c_char = arglist.as_mut_ptr(); - - let arg_pattern: *const c_char = CString::new("l|l").unwrap().into_raw(); + #[cfg(Py_3_13)] + let args_names = [ + c_str!("foo").as_ptr(), + c_str!("kw_bar").as_ptr(), + ptr::null_mut(), + ]; ffi::PyArg_ParseTupleAndKeywords( args, kwds, - arg_pattern, - arglist_ptr, - foo_ptr, - bar_ptr, + c_str!("l|l").as_ptr(), + #[cfg(Py_3_13)] + args_names.as_ptr(), + #[cfg(not(Py_3_13))] + args_names.as_mut_ptr(), + &mut foo, + &mut bar, ); + #[cfg(not(Py_3_13))] + drop(std::ffi::CString::from_raw(args_names[0])); + #[cfg(not(Py_3_13))] + drop(std::ffi::CString::from_raw(args_names[1])); + ffi::PyLong_FromLong(foo * bar) }