Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge master into the abi3 branch to resolve conflicts #1220

Merged
merged 49 commits into from
Oct 10, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
b66a925
treat Anaconda python as shared
rob-thatcher Sep 11, 2020
118646d
update changelog
rob-thatcher Sep 11, 2020
e3408e8
Merge pull request #1175 from thatcr/thatcr-fix-anaconda-python
davidhewitt Sep 11, 2020
32be8d9
Release 0.12
davidhewitt Sep 10, 2020
5ad89de
Fix date in changelog
davidhewitt Sep 12, 2020
b7f45c4
Merge pull request #1173 from PyO3/release-0.12
davidhewitt Sep 12, 2020
62ad53f
Don't consider it cross-compilation when building for 32-bit Windows …
alex Sep 12, 2020
d530e46
Update CHANGELOG.md
alex Sep 12, 2020
00a8700
Merge pull request #1178 from davidhewitt/fix-changelog-date
davidhewitt Sep 12, 2020
8c01162
Merge branch 'master' into patch-1
alex Sep 12, 2020
10f8c24
Update CHANGELOG.md
alex Sep 12, 2020
448f0bb
Merge pull request #1179 from alex/patch-1
kngwyu Sep 13, 2020
a0960f8
Fix compilation on platforms that don't use i8 for c_char (#1182)
mtreinish Sep 14, 2020
07f9ae2
Fix link in changelog
davidhewitt Sep 15, 2020
f36fb4a
Merge pull request #1192 from PyO3/davidhewitt-patch-5
davidhewitt Sep 16, 2020
e0775c3
Update Wasmer Python extension link
syrusakbary Sep 16, 2020
5fe1a44
fixed markdown syntax
alex Sep 16, 2020
309ab16
Merge pull request #1194 from syrusakbary/patch-1
davidhewitt Sep 16, 2020
c1b3e06
Merge pull request #1196 from alex/patch-1
kngwyu Sep 16, 2020
2213ab3
Fix doc redirect on release
davidhewitt Sep 16, 2020
88358de
Merge pull request #1197 from davidhewitt/update-doc-redirect
davidhewitt Sep 16, 2020
ba360bc
Fix doc update on release
davidhewitt Sep 16, 2020
037ec83
Merge pull request #1198 from PyO3/davidhewitt-patch-5
davidhewitt Sep 16, 2020
c058155
Release 0.12.1
davidhewitt Sep 15, 2020
15587f1
Merge pull request #1191 from PyO3/release-0.12.1
davidhewitt Sep 16, 2020
fcf1d0c
Tidy up guide release
davidhewitt Sep 16, 2020
00440a7
Merge pull request #1199 from PyO3/davidhewitt-patch-6
davidhewitt Sep 17, 2020
0a346df
Add documentation for raw_pycfuntion
sebpuetz Sep 11, 2020
0ec10a2
Merge pull request #1174 from sebpuetz/raw-pycfun-docs
davidhewitt Sep 19, 2020
61c388e
Update paste requirement from 0.1.6 to 1.0.1
dependabot[bot] Sep 21, 2020
63ea36f
Merge pull request #1204 from PyO3/dependabot/cargo/paste-1.0.1
kngwyu Sep 23, 2020
df984ec
Keyword only arguments (#1209)
dvermd Oct 1, 2020
41bd448
Add CHANGELOG entry for #1209.
davidhewitt Oct 1, 2020
37ce406
Merge pull request #1210 from PyO3/kwoa-changelog
kngwyu Oct 1, 2020
2e22066
Do not test PyPy on Windows
kngwyu Oct 8, 2020
7dadafb
Merge pull request #1215 from PyO3/actions-pypy-fix
kngwyu Oct 8, 2020
ddfbee4
Add null-check for function's documents
kngwyu Sep 9, 2020
41c2f5a
Use &'static CStr for representing method names and docs
kngwyu Oct 8, 2020
b42886a
Change PyCFunction to take &'static str as a function name
kngwyu Oct 8, 2020
9ee6da8
Add more comments to class/methods.rs and Reduce LOC
kngwyu Oct 8, 2020
4d00821
Add wrapper for PyErr_CheckSignals() to Python.
birkenfeld Oct 7, 2020
ff64431
Add a CHANGELOG entry
kngwyu Oct 8, 2020
359d878
Fix clippy warnings
kngwyu Oct 8, 2020
1d34ed7
Merge pull request #1214 from birkenfeld/signals
kngwyu Oct 8, 2020
e7092fe
Make PyCFunction more backward-compatible
kngwyu Oct 8, 2020
2684547
Make types in class::methods #[doc(hidden)]
kngwyu Oct 9, 2020
cb90c51
Merge pull request #1169 from PyO3/doc-null-check
kngwyu Oct 10, 2020
140790b
Merge branch 'master' into abi3-merge-master
alex Oct 10, 2020
398369f
Fixed warning
alex Oct 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions guide/src/function.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,31 @@ Type: builtin_function_or_method

## Closures

Currently, there are no conversions between `Fn`s in Rust and callables in Python. This would definitely be possible and very useful, so contributions are welcome. In the meantime, you can do the following:
Currently, there are no conversions between `Fn`s in Rust and callables in Python. This would
definitely be possible and very useful, so contributions are welcome. In the meantime, you can do
the following:

### Calling Python functions in Rust

You can use [`PyAny::is_callable`] to check if you have a callable object. `is_callable` will return `true` for functions (including lambdas), methods and objects with a `__call__` method. You can call the object with [`PyAny::call`] with the args as first parameter and the kwargs (or `None`) as second parameter. There are also [`PyAny::call0`] with no args and [`PyAny::call1`] with only positional args.
You can pass Python `def`'d functions and built-in functions to Rust functions `[PyFunction]`
corresponds to regular Python functions while `[PyCFunction]` describes built-ins such as
`repr()`.

You can also use [`PyAny::is_callable`] to check if you have a callable object. `is_callable` will
return `true` for functions (including lambdas), methods and objects with a `__call__` method.
You can call the object with [`PyAny::call`] with the args as first parameter and the kwargs
(or `None`) as second parameter. There are also [`PyAny::call0`] with no args and [`PyAny::call1`]
with only positional args.

### Calling Rust functions in Python

If you have a static function, you can expose it with `#[pyfunction]` and use [`wrap_pyfunction!`] to get the corresponding [`PyObject`]. For dynamic functions, e.g. lambdas and functions that were passed as arguments, you must put them in some kind of owned container, e.g. a `Box`. (A long-term solution will be a special container similar to wasm-bindgen's `Closure`). You can then use a `#[pyclass]` struct with that container as a field as a way to pass the function over the FFI barrier. You can even make that class callable with `__call__` so it looks like a function in Python code.
If you have a static function, you can expose it with `#[pyfunction]` and use [`wrap_pyfunction!`]
to get the corresponding [`PyCFunction`]. For dynamic functions, e.g. lambdas and functions that
were passed as arguments, you must put them in some kind of owned container, e.g. a `Box`.
(A long-term solution will be a special container similar to wasm-bindgen's `Closure`). You can
then use a `#[pyclass]` struct with that container as a field as a way to pass the function over
the FFI barrier. You can even make that class callable with `__call__` so it looks like a function
in Python code.

[`PyAny::is_callable`]: https://docs.rs/pyo3/latest/pyo3/struct.PyAny.html#tymethod.is_callable
[`PyAny::call`]: https://docs.rs/pyo3/latest/pyo3/struct.PyAny.html#tymethod.call
Expand Down Expand Up @@ -233,3 +249,15 @@ fn module_with_fn(py: Python, m: &PyModule) -> PyResult<()> {

# fn main() {}
```

## Accessing the FFI functions

In order to make Rust functions callable from Python, PyO3 generates a
`extern "C" Fn(slf: *mut PyObject, args: *mut PyObject, kwargs: *mut PyObject) -> *mut Pyobject`
function and embeds the call to the Rust function inside this FFI-wrapper function. This
wrapper handles extraction of the regular arguments and the keyword arguments from the input
`PyObjects`. Since this function is not user-defined but required to build a `PyCFunction`, PyO3
offers the `raw_pycfunction!()` macro to get the identifier of this generated wrapper.

The `wrap_pyfunction` macro can be used to directly get a `PyCFunction` given a
`#[pyfunction]` and a `PyModule`: `wrap_pyfunction!(rust_fun, module)`.
19 changes: 19 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,25 @@ macro_rules! wrap_pyfunction {
/// Returns the function that is called in the C-FFI.
///
/// Use this together with `#[pyfunction]` and [types::PyCFunction].
/// ```
/// use pyo3::prelude::*;
/// use pyo3::types::PyCFunction;
/// use pyo3::raw_pycfunction;
///
/// #[pyfunction]
/// fn some_fun() -> PyResult<()> {
/// Ok(())
/// }
///
/// #[pymodule]
/// fn module(_py: Python, module: &PyModule) -> PyResult<()> {
/// let ffi_wrapper_fun = raw_pycfunction!(some_fun);
/// let docs = "Some documentation string with null-termination\0";
/// let py_cfunction =
/// PyCFunction::new_with_keywords(ffi_wrapper_fun, "function_name", docs, module.into())?;
/// module.add_function(py_cfunction)
/// }
/// ```
#[macro_export]
macro_rules! raw_pycfunction {
($function_name: ident) => {{
Expand Down
2 changes: 2 additions & 0 deletions src/types/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pyobject_native_var_type!(PyCFunction, ffi::PyCFunction_Type, ffi::PyCFunction_C

impl PyCFunction {
/// Create a new built-in function with keywords.
///
/// See [raw_pycfunction] for documentation on how to get the `fun` argument.
pub fn new_with_keywords<'a>(
fun: ffi::PyCFunctionWithKeywords,
name: &str,
Expand Down