Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ffi: update modsupport.rs for Python 3.13 (#4420)
Browse files Browse the repository at this point in the history
davidhewitt committed Sep 3, 2024
1 parent 5e6e432 commit 4275773
Showing 4 changed files with 35 additions and 47 deletions.
1 change: 1 addition & 0 deletions newsfragments/4420.fixed.md
Original file line number Diff line number Diff line change
@@ -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.
1 change: 1 addition & 0 deletions newsfragments/4420.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove FFI definition of private variable `_Py_PackageContext`.
39 changes: 8 additions & 31 deletions pyo3-ffi/src/modsupport.rs
Original file line number Diff line number Diff line change
@@ -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;
}
41 changes: 25 additions & 16 deletions tests/test_pyfunction.rs
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 4275773

Please sign in to comment.