[PATCH 7 of 7] rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara
yuya at tcha.org
Sun Oct 13 05:47:10 EDT 2019
# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1570954064 -32400
# Sun Oct 13 17:07:44 2019 +0900
# Node ID 6c8410bd4ce786ceca53986514a1fbda5f097f2d
# Parent 2d7671cc1d717f3ed3890e47324e4ed479529466
rust-cpython: leverage upstreamed py_capsule_fn!() macro
diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs
--- a/rust/hg-cpython/src/cindex.rs
+++ b/rust/hg-cpython/src/cindex.rs
@@ -10,18 +10,20 @@
//! Ideally, we should use an Index entirely implemented in Rust,
//! but this will take some time to get there.
-use crate::python_sys::{self, PyCapsule_Import};
-use cpython::{PyClone, PyErr, PyObject, PyResult, Python};
+use crate::python_sys;
+use cpython::{PyClone, PyObject, PyResult, Python};
use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION};
use libc::c_int;
-use std::ffi::CStr;
-use std::mem::transmute;
-type IndexParentsFn = unsafe extern "C" fn(
- index: *mut python_sys::PyObject,
- rev: c_int,
- ps: *mut [c_int; 2],
-) -> c_int;
+py_capsule_fn!(
+ from mercurial.cext.parsers import index_get_parents_CAPI
+ as get_parents_capi
+ signature (
+ index: *mut python_sys::PyObject,
+ rev: c_int,
+ ps: *mut [c_int; 2],
+ ) -> c_int
+);
/// A `Graph` backed up by objects and functions from revlog.c
///
@@ -57,14 +59,14 @@ type IndexParentsFn = unsafe extern "C"
/// mechanisms in other contexts.
pub struct Index {
index: PyObject,
- parents: IndexParentsFn,
+ parents: get_parents_capi::CapsuleFn,
}
impl Index {
pub fn new(py: Python, index: PyObject) -> PyResult<Self> {
Ok(Index {
index: index,
- parents: decapsule_parents_fn(py)?,
+ parents: get_parents_capi::retrieve(py)?,
})
}
}
@@ -99,31 +101,3 @@ impl Graph for Index {
}
}
}
-
-/// Return the `index_get_parents` function of the parsers C Extension module.
-///
-/// A pointer to the function is stored in the `parsers` module as a
-/// standard [Python capsule](https://docs.python.org/2/c-api/capsule.html).
-///
-/// This function retrieves the capsule and casts the function pointer
-///
-/// Casting function pointers is one of the rare cases of
-/// legitimate use cases of `mem::transmute()` (see
-/// https://doc.rust-lang.org/std/mem/fn.transmute.html of
-/// `mem::transmute()`.
-/// It is inappropriate for architectures where
-/// function and data pointer sizes differ (so-called "Harvard
-/// architectures"), but these are nowadays mostly DSPs
-/// and microcontrollers, hence out of our scope.
-fn decapsule_parents_fn(py: Python) -> PyResult<IndexParentsFn> {
- unsafe {
- let caps_name = CStr::from_bytes_with_nul_unchecked(
- b"mercurial.cext.parsers.index_get_parents_CAPI\0",
- );
- let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0);
- if from_caps.is_null() {
- return Err(PyErr::fetch(py));
- }
- Ok(transmute(from_caps))
- }
-}
diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs
--- a/rust/hg-cpython/src/dirstate.rs
+++ b/rust/hg-cpython/src/dirstate.rs
@@ -15,7 +15,7 @@ mod dirs_multiset;
mod dirstate_map;
use crate::dirstate::{dirs_multiset::Dirs, dirstate_map::DirstateMap};
-use crate::python_sys::{self, PyCapsule_Import};
+use crate::python_sys;
use cpython::{
exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence,
Python,
@@ -26,8 +26,6 @@ use hg::{
};
use libc::{c_char, c_int};
use std::convert::TryFrom;
-use std::ffi::CStr;
-use std::mem::transmute;
// C code uses a custom `dirstate_tuple` type, checks in multiple instances
// for this type, and raises a Python `Exception` if the check does not pass.
@@ -35,34 +33,23 @@ use std::mem::transmute;
// would be a good idea in the near future to remove it entirely to allow
// for a pure Python tuple of the same effective structure to be used,
// rendering this type and the capsule below useless.
-type MakeDirstateTupleFn = unsafe extern "C" fn(
- state: c_char,
- mode: c_int,
- size: c_int,
- mtime: c_int,
-) -> *mut python_sys::PyObject;
-
-// This is largely a copy/paste from cindex.rs, pending the merge of a
-// `py_capsule_fn!` macro in the rust-cpython project:
-// https://github.com/dgrunwald/rust-cpython/pull/169
-fn decapsule_make_dirstate_tuple(py: Python) -> PyResult<MakeDirstateTupleFn> {
- unsafe {
- let caps_name = CStr::from_bytes_with_nul_unchecked(
- b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0",
- );
- let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0);
- if from_caps.is_null() {
- return Err(PyErr::fetch(py));
- }
- Ok(transmute(from_caps))
- }
-}
+py_capsule_fn!(
+ from mercurial.cext.parsers import make_dirstate_tuple_CAPI
+ as make_dirstate_tuple_capi
+ signature (
+ state: c_char,
+ mode: c_int,
+ size: c_int,
+ mtime: c_int,
+ ) -> *mut python_sys::PyObject
+);
pub fn make_dirstate_tuple(
py: Python,
entry: &DirstateEntry,
) -> PyResult<PyObject> {
- let make = decapsule_make_dirstate_tuple(py)?;
+ // might be silly to retrieve capsule function in hot loop
+ let make = make_dirstate_tuple_capi::retrieve(py)?;
let &DirstateEntry {
state,
More information about the Mercurial-devel
mailing list