Skip to content

Commit 6f03a54

Browse files
authored
cleans up PyCFunction::internal_new (#3910)
This deduplicates some code around `PyCFunction::internal_new`
1 parent a3ad28b commit 6f03a54

File tree

3 files changed

+19
-43
lines changed

3 files changed

+19
-43
lines changed

pyo3-macros-backend/src/pyfunction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ pub fn impl_wrap_pyfunction(
273273
pub fn add_to_module(module: &#krate::Bound<'_, #krate::types::PyModule>) -> #krate::PyResult<()> {
274274
use #krate::prelude::PyModuleMethods;
275275
use ::std::convert::Into;
276-
module.add_function(#krate::types::PyCFunction::internal_new(&DEF, module.as_gil_ref().into())?)
276+
module.add_function(#krate::types::PyCFunction::internal_new(module.py(), &DEF, module.into())?)
277277
}
278278
}
279279

src/impl_/pyfunction.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
types::{PyCFunction, PyModule},
3-
Borrowed, Bound, PyResult, Python,
3+
Borrowed, Bound, PyNativeType, PyResult, Python,
44
};
55

66
pub use crate::impl_::pymethods::PyMethodDef;
@@ -13,39 +13,40 @@ pub trait WrapPyFunctionArg<'py, T> {
1313

1414
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Bound<'py, PyModule> {
1515
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
16-
PyCFunction::internal_new_bound(self.py(), method_def, Some(&self))
16+
PyCFunction::internal_new(self.py(), method_def, Some(&self))
1717
}
1818
}
1919

2020
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Bound<'py, PyModule> {
2121
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
22-
PyCFunction::internal_new_bound(self.py(), method_def, Some(self))
22+
PyCFunction::internal_new(self.py(), method_def, Some(self))
2323
}
2424
}
2525

2626
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Borrowed<'_, 'py, PyModule> {
2727
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
28-
PyCFunction::internal_new_bound(self.py(), method_def, Some(&self))
28+
PyCFunction::internal_new(self.py(), method_def, Some(&self))
2929
}
3030
}
3131

3232
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, 'py, PyModule> {
3333
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
34-
PyCFunction::internal_new_bound(self.py(), method_def, Some(self))
34+
PyCFunction::internal_new(self.py(), method_def, Some(self))
3535
}
3636
}
3737

3838
// For Python<'py>, only the GIL Ref form exists to avoid causing type inference to kick in.
3939
// The `wrap_pyfunction_bound!` macro is needed for the Bound form.
4040
impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for Python<'py> {
4141
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> {
42-
PyCFunction::internal_new(method_def, self.into()).map(Bound::into_gil_ref)
42+
PyCFunction::internal_new(self, method_def, None).map(Bound::into_gil_ref)
4343
}
4444
}
4545

4646
impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for &'py PyModule {
4747
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> {
48-
PyCFunction::internal_new(method_def, self.into()).map(Bound::into_gil_ref)
48+
PyCFunction::internal_new(self.py(), method_def, Some(&self.as_borrowed()))
49+
.map(Bound::into_gil_ref)
4950
}
5051
}
5152

@@ -63,6 +64,6 @@ where
6364

6465
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for OnlyBound<Python<'py>> {
6566
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
66-
PyCFunction::internal_new_bound(self.0, method_def, None)
67+
PyCFunction::internal_new(self.0, method_def, None)
6768
}
6869
}

src/types/function.rs

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
impl_::pymethods::{self, PyMethodDef},
1010
types::{PyCapsule, PyDict, PyModule, PyString, PyTuple},
1111
};
12-
use crate::{Bound, IntoPy, Py, PyAny, PyResult, Python};
12+
use crate::{Bound, IntoPy, Py, PyAny, PyNativeType, PyResult, Python};
1313
use std::cell::UnsafeCell;
1414
use std::ffi::CStr;
1515

@@ -34,13 +34,15 @@ impl PyCFunction {
3434
doc: &'static str,
3535
py_or_module: PyFunctionArguments<'a>,
3636
) -> PyResult<&'a Self> {
37+
let (py, module) = py_or_module.into_py_and_maybe_module();
3738
Self::internal_new(
39+
py,
3840
&PyMethodDef::cfunction_with_keywords(
3941
name,
4042
pymethods::PyCFunctionWithKeywords(fun),
4143
doc,
4244
),
43-
py_or_module,
45+
module.map(PyNativeType::as_borrowed).as_deref(),
4446
)
4547
.map(Bound::into_gil_ref)
4648
}
@@ -53,7 +55,7 @@ impl PyCFunction {
5355
doc: &'static str,
5456
module: Option<&Bound<'py, PyModule>>,
5557
) -> PyResult<Bound<'py, Self>> {
56-
Self::internal_new_bound(
58+
Self::internal_new(
5759
py,
5860
&PyMethodDef::cfunction_with_keywords(
5961
name,
@@ -78,9 +80,11 @@ impl PyCFunction {
7880
doc: &'static str,
7981
py_or_module: PyFunctionArguments<'a>,
8082
) -> PyResult<&'a Self> {
83+
let (py, module) = py_or_module.into_py_and_maybe_module();
8184
Self::internal_new(
85+
py,
8286
&PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc),
83-
py_or_module,
87+
module.map(PyNativeType::as_borrowed).as_deref(),
8488
)
8589
.map(Bound::into_gil_ref)
8690
}
@@ -93,7 +97,7 @@ impl PyCFunction {
9397
doc: &'static str,
9498
module: Option<&Bound<'py, PyModule>>,
9599
) -> PyResult<Bound<'py, Self>> {
96-
Self::internal_new_bound(
100+
Self::internal_new(
97101
py,
98102
&PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc),
99103
module,
@@ -180,35 +184,6 @@ impl PyCFunction {
180184

181185
#[doc(hidden)]
182186
pub fn internal_new<'py>(
183-
method_def: &PyMethodDef,
184-
py_or_module: PyFunctionArguments<'py>,
185-
) -> PyResult<Bound<'py, Self>> {
186-
let (py, module) = py_or_module.into_py_and_maybe_module();
187-
let (mod_ptr, module_name): (_, Option<Py<PyString>>) = if let Some(m) = module {
188-
let mod_ptr = m.as_ptr();
189-
(mod_ptr, Some(m.name()?.into_py(py)))
190-
} else {
191-
(std::ptr::null_mut(), None)
192-
};
193-
let (def, destructor) = method_def.as_method_def()?;
194-
195-
// FIXME: stop leaking the def and destructor
196-
let def = Box::into_raw(Box::new(def));
197-
std::mem::forget(destructor);
198-
199-
let module_name_ptr = module_name
200-
.as_ref()
201-
.map_or(std::ptr::null_mut(), Py::as_ptr);
202-
203-
unsafe {
204-
ffi::PyCFunction_NewEx(def, mod_ptr, module_name_ptr)
205-
.assume_owned_or_err(py)
206-
.downcast_into_unchecked()
207-
}
208-
}
209-
210-
#[doc(hidden)]
211-
pub(crate) fn internal_new_bound<'py>(
212187
py: Python<'py>,
213188
method_def: &PyMethodDef,
214189
module: Option<&Bound<'py, PyModule>>,

0 commit comments

Comments
 (0)