Many small improvements
This commit is contained in:
parent
55d0917419
commit
d0ed68414a
24
.travis.yml
24
.travis.yml
|
@ -4,21 +4,23 @@ language: python
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
pip: true
|
pip: true
|
||||||
cargo: true
|
directories:
|
||||||
|
- $HOME/.cargo
|
||||||
|
- $TRAVIS_BUILD_DIR/target
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- python: "2.7"
|
- python: "2.7"
|
||||||
env: FEATURES=python2
|
env: FEATURES=python2
|
||||||
- python: "3.5"
|
- python: "3.5"
|
||||||
env: FEATURES=python3
|
env: FEATURES=python3
|
||||||
- python: "3.6"
|
- python: "3.6"
|
||||||
env: FEATURES=python3
|
env: FEATURES=python3
|
||||||
- python: "3.7-dev"
|
- python: "3.7-dev"
|
||||||
env: FEATURES=python3
|
env: FEATURES=python3
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- python: "3.7-dev"
|
- python: "3.7-dev"
|
||||||
env: FEATURES=python3
|
env: FEATURES=python3
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -15,22 +15,22 @@ build = "build.rs"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "PyO3/pyo3", branch = "master" }
|
travis-ci = { repository = "PyO3/pyo3", branch = "master" }
|
||||||
appveyor = { repository = "PyO3/pyo3" }
|
appveyor = { repository = "fafhrd91/pyo3" }
|
||||||
codecov = { repository = "PyO3/pyo3", branch = "master", service = "github" }
|
codecov = { repository = "PyO3/pyo3", branch = "master", service = "github" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2.42"
|
||||||
spin = "0.4.6"
|
spin = "0.4.8"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2.5"
|
||||||
pyo3cls = { path = "pyo3cls", version = "0.4.0" }
|
pyo3cls = { path = "pyo3cls", version = "0.4.0" }
|
||||||
mashup = "0.1.5"
|
mashup = "0.1.5"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
docmatic = "^0.1.2"
|
docmatic = "0.1.2"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
regex = "1.0"
|
regex = "1.0.2"
|
||||||
version_check = "0.1.3"
|
version_check = "0.1.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# PyO3
|
# PyO3
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/PyO3/pyo3.svg?branch=master)](https://travis-ci.org/PyO3/pyo3)
|
[![Build Status](https://travis-ci.org/PyO3/pyo3.svg?branch=master)](https://travis-ci.org/PyO3/pyo3)
|
||||||
[![Build Status](https://ci.appveyor.com/api/projects/status/github/PyO3/pyo3?branch=master&svg=true)](https://ci.appveyor.com/project/fafhrd91/pyo3)
|
[![Build Status](https://ci.appveyor.com/api/projects/status/github/fafhrd91/pyo3?branch=master&svg=true)](https://ci.appveyor.com/project/fafhrd91/pyo3)
|
||||||
[![codecov](https://codecov.io/gh/PyO3/pyo3/branch/master/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3)
|
[![codecov](https://codecov.io/gh/PyO3/pyo3/branch/master/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3)
|
||||||
[![crates.io](http://meritbadge.herokuapp.com/pyo3)](https://crates.io/crates/pyo3)
|
[![crates.io](http://meritbadge.herokuapp.com/pyo3)](https://crates.io/crates/pyo3)
|
||||||
[![Join the dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby)
|
[![Join the dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby)
|
||||||
|
|
20
build.rs
20
build.rs
|
@ -6,6 +6,7 @@ use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::process::Stdio;
|
||||||
use version_check::{is_min_date, is_min_version, supports_features};
|
use version_check::{is_min_date, is_min_version, supports_features};
|
||||||
|
|
||||||
// Specifies the minimum nightly version needed to compile pyo3.
|
// Specifies the minimum nightly version needed to compile pyo3.
|
||||||
|
@ -172,12 +173,12 @@ fn cfg_line_for_var(key: &str, val: &str) -> Option<String> {
|
||||||
fn run_python_script(interpreter: &str, script: &str) -> Result<String, String> {
|
fn run_python_script(interpreter: &str, script: &str) -> Result<String, String> {
|
||||||
let out = Command::new(interpreter)
|
let out = Command::new(interpreter)
|
||||||
.args(&["-c", script])
|
.args(&["-c", script])
|
||||||
|
.stderr(Stdio::inherit())
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| format!("failed to run python interpreter:\n\n{}", e))?;
|
.map_err(|e| format!("failed to run python interpreter:\n\n{}", e))?;
|
||||||
|
|
||||||
if !out.status.success() {
|
if !out.status.success() {
|
||||||
let stderr = String::from_utf8(out.stderr).unwrap();
|
return Err(format!("python script failed"));
|
||||||
return Err(format!("python script failed with stderr:\n\n{}", stderr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(String::from_utf8(out.stdout).unwrap())
|
Ok(String::from_utf8(out.stdout).unwrap())
|
||||||
|
@ -306,11 +307,16 @@ fn find_interpreter_and_get_config(
|
||||||
|
|
||||||
/// Extract compilation vars from the specified interpreter.
|
/// Extract compilation vars from the specified interpreter.
|
||||||
fn get_config_from_interpreter(interpreter: &str) -> Result<(PythonVersion, Vec<String>), String> {
|
fn get_config_from_interpreter(interpreter: &str) -> Result<(PythonVersion, Vec<String>), String> {
|
||||||
let script = "import sys; import sysconfig; print(sys.version_info[0:2]); \
|
let script = r#"
|
||||||
print(sysconfig.get_config_var('LIBDIR')); \
|
import sys
|
||||||
print(sysconfig.get_config_var('Py_ENABLE_SHARED')); \
|
import sysconfig
|
||||||
print(sysconfig.get_config_var('LDVERSION') or sysconfig.get_config_var('py_version_short')); \
|
|
||||||
print(sys.exec_prefix);";
|
print(sys.version_info[0:2])
|
||||||
|
print(sysconfig.get_config_var('LIBDIR'))
|
||||||
|
print(sysconfig.get_config_var('Py_ENABLE_SHARED'))
|
||||||
|
print(sysconfig.get_config_var('LDVERSION') or sysconfig.get_config_var('py_version_short'))
|
||||||
|
print(sys.exec_prefix)
|
||||||
|
"#;
|
||||||
let out = run_python_script(interpreter, script)?;
|
let out = run_python_script(interpreter, script)?;
|
||||||
let lines: Vec<String> = out.lines().map(|line| line.to_owned()).collect();
|
let lines: Vec<String> = out.lines().map(|line| line.to_owned()).collect();
|
||||||
let interpreter_version = get_interpreter_version(&lines[0])?;
|
let interpreter_version = get_interpreter_version(&lines[0])?;
|
||||||
|
|
|
@ -38,13 +38,7 @@ fi
|
||||||
### Setup python linker flags ##################################################
|
### Setup python linker flags ##################################################
|
||||||
|
|
||||||
PYTHON_LIB=$(python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
|
PYTHON_LIB=$(python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
|
||||||
LIBRARY_PATH="$LIBRARY_PATH:$PYTHON_LIB"
|
|
||||||
|
|
||||||
# delete any possible empty components
|
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PYTHON_LIB:$HOME/rust/lib"
|
||||||
# https://github.com/google/pulldown-cmark/issues/122#issuecomment-364948741
|
|
||||||
LIBRARY_PATH=$(echo ${LIBRARY_PATH} | sed -E -e 's/^:*//' -e 's/:*$//' -e 's/:+/:/g')
|
|
||||||
|
|
||||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LIBRARY_PATH:$HOME/rust/lib"
|
|
||||||
|
|
||||||
python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"
|
|
||||||
echo ${LD_LIBRARY_PATH}
|
echo ${LD_LIBRARY_PATH}
|
|
@ -4,7 +4,7 @@ name = "word-count"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rayon = "1.0"
|
rayon = "1.0.2"
|
||||||
pyo3 = { path = "../..", features = ["extension-module"] }
|
pyo3 = { path = "../..", features = ["extension-module"] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
2
examples/word-count/pyproject.toml
Normal file
2
examples/word-count/pyproject.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools", "wheel", "setuptools-rust"]
|
|
@ -25,8 +25,7 @@ class PyTest(TestCommand):
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
errno = subprocess.call([sys.executable, "-m", "pytest", "tests"])
|
subprocess.check_call([sys.executable, "-m", "pytest", "tests"])
|
||||||
raise SystemExit(errno)
|
|
||||||
|
|
||||||
|
|
||||||
setup_requires = ["setuptools-rust>=0.10.1", "wheel"]
|
setup_requires = ["setuptools-rust>=0.10.1", "wheel"]
|
||||||
|
|
|
@ -54,3 +54,16 @@ fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
### Calling a python function in rust
|
||||||
|
|
||||||
|
You can use `ObjectProtocol::is_callable` to check if you got a callable, which is true for functions (including lambdas), methods and objects with a `__call__` method. You can call the object with `ObjectProtocol::call` with the args as first parameter and the kwargs (or `NoArgs`) as second paramter. There are also `ObjectProtocol::call0` with no args and `ObjectProtocol::call1` with only the args.
|
||||||
|
|
||||||
|
### Calling rust `Fn`s in python
|
||||||
|
|
||||||
|
If you have a static function, you can expose it with `#[pyfunction]` and use `wrap_function!` to get the corresponding `PyObject`. For dynamic functions, e.g. lambda and functions that were passed as arguments, you must put them in some kind of owned container, e.g. a box. (Long-Term a special container similar to wasm-bindgen's `Closure` should take care of that). You can than use a `#[pyclass]` struct with that container as 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.
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@ categories = ["api-bindings", "development-tools::ffi"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log="0.4"
|
log= "0.4.3"
|
||||||
quote="0.6"
|
quote= "0.6.4"
|
||||||
|
|
||||||
[dependencies.proc-macro2]
|
[dependencies.proc-macro2]
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
features = ["nightly"]
|
features = ["nightly"]
|
||||||
|
|
||||||
[dependencies.syn]
|
[dependencies.syn]
|
||||||
version="0.14"
|
version= "0.14.5"
|
||||||
features=["full", "parsing", "printing", "extra-traits"]
|
features=["full", "parsing", "printing", "extra-traits"]
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub fn py2_init(fnname: &syn::Ident, name: &syn::Ident, doc: syn::Lit) -> TokenS
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_snake_case, unused_imports)]
|
#[allow(non_snake_case)]
|
||||||
pub unsafe extern "C" fn #cb_name() {
|
pub unsafe extern "C" fn #cb_name() {
|
||||||
// initialize python
|
// initialize python
|
||||||
::pyo3::init_once();
|
::pyo3::init_once();
|
||||||
|
@ -281,7 +281,6 @@ fn function_c_wrapper(name: &syn::Ident, spec: &method::FnSpec) -> TokenStream {
|
||||||
let body_to_result = py_method::body_to_result(&body, spec);
|
let body_to_result = py_method::body_to_result(&body, spec);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[allow(unused_variables, unused_imports)]
|
|
||||||
unsafe extern "C" fn __wrap(
|
unsafe extern "C" fn __wrap(
|
||||||
_slf: *mut ::pyo3::ffi::PyObject,
|
_slf: *mut ::pyo3::ffi::PyObject,
|
||||||
_args: *mut ::pyo3::ffi::PyObject,
|
_args: *mut ::pyo3::ffi::PyObject,
|
||||||
|
|
|
@ -14,10 +14,10 @@ license = "Apache-2.0"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote="0.6"
|
quote= "0.6.4"
|
||||||
|
|
||||||
[dependencies.syn]
|
[dependencies.syn]
|
||||||
version="0.14"
|
version= "0.14.5"
|
||||||
features=["full", "parsing", "printing", "extra-traits"]
|
features=["full", "parsing", "printing", "extra-traits"]
|
||||||
|
|
||||||
[dependencies.pyo3-derive-backend]
|
[dependencies.pyo3-derive-backend]
|
||||||
|
|
|
@ -98,21 +98,21 @@ mod tupleobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3
|
||||||
mod enumobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod enumobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod methodobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod methodobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod moduleobject;
|
mod moduleobject;
|
||||||
mod setobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod setobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
// mod funcobject; TODO excluded by PEP-384
|
// mod funcobject; TODO excluded by PEP-384
|
||||||
// mod classobject; TODO excluded by PEP-384
|
// mod classobject; TODO excluded by PEP-384
|
||||||
mod fileobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod fileobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod pycapsule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod pycapsule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod sliceobject;
|
mod sliceobject;
|
||||||
mod traceback; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod traceback; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
// mod cellobject; TODO excluded by PEP-384
|
// mod cellobject; TODO excluded by PEP-384
|
||||||
mod descrobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod descrobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod genobject; // TODO excluded by PEP-384
|
mod genobject; // TODO excluded by PEP-384
|
||||||
mod iterobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod iterobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod structseq;
|
mod structseq;
|
||||||
mod warnings; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod warnings; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod weakrefobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod weakrefobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
// mod namespaceobject; TODO
|
// mod namespaceobject; TODO
|
||||||
|
|
||||||
mod codecs; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod codecs; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
mod pyerrors; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod pyerrors; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
|
@ -131,7 +131,7 @@ mod import;
|
||||||
mod intrcheck; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod intrcheck; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
#[cfg(Py_3_6)]
|
#[cfg(Py_3_6)]
|
||||||
mod osmodule;
|
mod osmodule;
|
||||||
mod sysmodule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod sysmodule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
|
|
||||||
mod bltinmodule;
|
mod bltinmodule;
|
||||||
mod objectabstract; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
mod objectabstract; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
|
||||||
|
|
|
@ -14,7 +14,6 @@ use python::{IntoPyDictPointer, IntoPyPointer, Python, ToPyPointer};
|
||||||
use typeob::PyTypeInfo;
|
use typeob::PyTypeInfo;
|
||||||
|
|
||||||
/// Python object model helper methods
|
/// Python object model helper methods
|
||||||
|
|
||||||
pub trait ObjectProtocol {
|
pub trait ObjectProtocol {
|
||||||
/// Determines whether this object has the given attribute.
|
/// Determines whether this object has the given attribute.
|
||||||
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
||||||
|
@ -517,14 +516,14 @@ where
|
||||||
FromPyObject::extract(self.into())
|
FromPyObject::extract(self.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_refcnt(&self) -> isize {
|
||||||
|
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||||
fn None(&self) -> PyObject {
|
fn None(&self) -> PyObject {
|
||||||
unsafe { PyObject::from_borrowed_ptr(self.py(), ffi::Py_None()) }
|
unsafe { PyObject::from_borrowed_ptr(self.py(), ffi::Py_None()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_refcnt(&self) -> isize {
|
|
||||||
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -2,11 +2,6 @@
|
||||||
//
|
//
|
||||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||||
|
|
||||||
use std;
|
|
||||||
use std::ffi::CString;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::os::raw::c_int;
|
|
||||||
|
|
||||||
use conversion::PyTryFrom;
|
use conversion::PyTryFrom;
|
||||||
use err::{PyDowncastError, PyErr, PyResult};
|
use err::{PyDowncastError, PyErr, PyResult};
|
||||||
use ffi;
|
use ffi;
|
||||||
|
@ -14,6 +9,10 @@ use instance::{AsPyRef, Py, PyToken};
|
||||||
use object::PyObject;
|
use object::PyObject;
|
||||||
use objects::{PyDict, PyModule, PyObjectRef, PyType};
|
use objects::{PyDict, PyModule, PyObjectRef, PyType};
|
||||||
use pythonrun::{self, GILGuard};
|
use pythonrun::{self, GILGuard};
|
||||||
|
use std;
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::os::raw::c_int;
|
||||||
use typeob::{PyObjectAlloc, PyTypeInfo, PyTypeObject};
|
use typeob::{PyObjectAlloc, PyTypeInfo, PyTypeObject};
|
||||||
|
|
||||||
/// Marker type that indicates that the GIL is currently held.
|
/// Marker type that indicates that the GIL is currently held.
|
||||||
|
@ -294,10 +293,11 @@ impl<'p> Python<'p> {
|
||||||
where
|
where
|
||||||
T: PyTypeInfo,
|
T: PyTypeInfo,
|
||||||
{
|
{
|
||||||
|
let p;
|
||||||
unsafe {
|
unsafe {
|
||||||
let p = pythonrun::register_owned(self, obj.into_ptr());
|
p = pythonrun::register_owned(self, obj.into_ptr());
|
||||||
<T as PyTryFrom>::try_from(p)
|
|
||||||
}
|
}
|
||||||
|
<T as PyTryFrom>::try_from(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register object in release pool, and do unchecked downcast to specific type.
|
/// Register object in release pool, and do unchecked downcast to specific type.
|
||||||
|
@ -463,7 +463,6 @@ impl<'p> Python<'p> {
|
||||||
/// Release `ffi::PyObject` pointer.
|
/// Release `ffi::PyObject` pointer.
|
||||||
/// Undefined behavior if the pointer is invalid.
|
/// Undefined behavior if the pointer is invalid.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
||||||
pub fn xdecref(self, ptr: *mut ffi::PyObject) {
|
pub fn xdecref(self, ptr: *mut ffi::PyObject) {
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
unsafe { ffi::Py_DECREF(ptr) };
|
unsafe { ffi::Py_DECREF(ptr) };
|
||||||
|
|
Loading…
Reference in a new issue