Skip to content

Commit 3927c45

Browse files
committed
ffi: update modsupport.rs for Python 3.13
1 parent 0a185cd commit 3927c45

File tree

4 files changed

+35
-47
lines changed

4 files changed

+35
-47
lines changed

newsfragments/4418.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Correct FFI definition `PyArg_ParseTupleAndKeywords` to take `*const *const c_char` instead of `*mut *mut c_char` on Python 3.13 and up.

newsfragments/4418.removed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Remove FFI definition of private variable `_Py_PackageContext`.

pyo3-ffi/src/modsupport.rs

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ extern "C" {
1414
arg1: *mut PyObject,
1515
arg2: *mut PyObject,
1616
arg3: *const c_char,
17-
arg4: *mut *mut c_char,
17+
#[cfg(not(Py_3_13))] arg4: *mut *mut c_char,
18+
#[cfg(Py_3_13)] arg4: *const *const c_char,
1819
...
1920
) -> c_int;
21+
22+
// skipped PyArg_VaParse
23+
// skipped PyArg_VaParseTupleAndKeywords
24+
2025
pub fn PyArg_ValidateKeywordArguments(arg1: *mut PyObject) -> c_int;
2126
#[cfg_attr(PyPy, link_name = "PyPyArg_UnpackTuple")]
2227
pub fn PyArg_UnpackTuple(
@@ -26,32 +31,10 @@ extern "C" {
2631
arg4: Py_ssize_t,
2732
...
2833
) -> c_int;
34+
2935
#[cfg_attr(PyPy, link_name = "PyPy_BuildValue")]
3036
pub fn Py_BuildValue(arg1: *const c_char, ...) -> *mut PyObject;
31-
// #[cfg_attr(PyPy, link_name = "_PyPy_BuildValue_SizeT")]
32-
//pub fn _Py_BuildValue_SizeT(arg1: *const c_char, ...)
33-
// -> *mut PyObject;
34-
// #[cfg_attr(PyPy, link_name = "PyPy_VaBuildValue")]
35-
36-
// skipped non-limited _PyArg_UnpackStack
37-
// skipped non-limited _PyArg_NoKeywords
38-
// skipped non-limited _PyArg_NoKwnames
39-
// skipped non-limited _PyArg_NoPositional
40-
// skipped non-limited _PyArg_BadArgument
41-
// skipped non-limited _PyArg_CheckPositional
42-
43-
//pub fn Py_VaBuildValue(arg1: *const c_char, arg2: va_list)
44-
// -> *mut PyObject;
45-
46-
// skipped non-limited _Py_VaBuildStack
47-
// skipped non-limited _PyArg_Parser
48-
49-
// skipped non-limited _PyArg_ParseTupleAndKeywordsFast
50-
// skipped non-limited _PyArg_ParseStack
51-
// skipped non-limited _PyArg_ParseStackAndKeywords
52-
// skipped non-limited _PyArg_VaParseTupleAndKeywordsFast
53-
// skipped non-limited _PyArg_UnpackKeywords
54-
// skipped non-limited _PyArg_Fini
37+
// skipped Py_VaBuildValue
5538

5639
#[cfg(Py_3_10)]
5740
#[cfg_attr(PyPy, link_name = "PyPyModule_AddObjectRef")]
@@ -159,9 +142,3 @@ pub unsafe fn PyModule_FromDefAndSpec(def: *mut PyModuleDef, spec: *mut PyObject
159142
},
160143
)
161144
}
162-
163-
#[cfg(not(Py_LIMITED_API))]
164-
#[cfg_attr(windows, link(name = "pythonXY"))]
165-
extern "C" {
166-
pub static mut _Py_PackageContext: *const c_char;
167-
}

tests/test_pyfunction.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,7 @@ fn test_pycfunction_new() {
363363
#[test]
364364
fn test_pycfunction_new_with_keywords() {
365365
use pyo3::ffi;
366-
use std::ffi::CString;
367-
use std::os::raw::{c_char, c_long};
366+
use std::os::raw::c_long;
368367
use std::ptr;
369368

370369
Python::with_gil(|py| {
@@ -375,28 +374,38 @@ fn test_pycfunction_new_with_keywords() {
375374
) -> *mut ffi::PyObject {
376375
let mut foo: c_long = 0;
377376
let mut bar: c_long = 0;
378-
let foo_ptr: *mut c_long = &mut foo;
379-
let bar_ptr: *mut c_long = &mut bar;
380377

381-
let foo_name = CString::new("foo").unwrap();
382-
let foo_name_raw: *mut c_char = foo_name.into_raw();
383-
let kw_bar_name = CString::new("kw_bar").unwrap();
384-
let kw_bar_name_raw: *mut c_char = kw_bar_name.into_raw();
378+
#[cfg(not(Py_3_13))]
379+
let foo_name = std::ffi::CString::new("foo").unwrap();
380+
#[cfg(not(Py_3_13))]
381+
let kw_bar_name = std::ffi::CString::new("kw_bar").unwrap();
382+
#[cfg(not(Py_3_13))]
383+
let mut args_names = [foo_name.into_raw(), kw_bar_name.into_raw(), ptr::null_mut()];
385384

386-
let mut arglist = vec![foo_name_raw, kw_bar_name_raw, ptr::null_mut()];
387-
let arglist_ptr: *mut *mut c_char = arglist.as_mut_ptr();
388-
389-
let arg_pattern: *const c_char = CString::new("l|l").unwrap().into_raw();
385+
#[cfg(Py_3_13)]
386+
let args_names = [
387+
c_str!("foo").as_ptr(),
388+
c_str!("kw_bar").as_ptr(),
389+
ptr::null_mut(),
390+
];
390391

391392
ffi::PyArg_ParseTupleAndKeywords(
392393
args,
393394
kwds,
394-
arg_pattern,
395-
arglist_ptr,
396-
foo_ptr,
397-
bar_ptr,
395+
c_str!("l|l").as_ptr(),
396+
#[cfg(Py_3_13)]
397+
args_names.as_ptr(),
398+
#[cfg(not(Py_3_13))]
399+
args_names.as_mut_ptr(),
400+
&mut foo,
401+
&mut bar,
398402
);
399403

404+
#[cfg(not(Py_3_13))]
405+
drop(std::ffi::CString::from_raw(args_names[0]));
406+
#[cfg(not(Py_3_13))]
407+
drop(std::ffi::CString::from_raw(args_names[1]));
408+
400409
ffi::PyLong_FromLong(foo * bar)
401410
}
402411

0 commit comments

Comments
 (0)