# HG changeset patch # User Georges Racinet # Date 1574873998 -3600 # Node ID f384d68d8ea8ab97e83a65f45cb6894c634c43c4 # Parent 26cf356ae772dda92d2eb2ae2ce21c773e56d40e revlog: made C Capsule an array of function pointers Although it's perfectly valid to put a function pointer in a capsule, as we've been doing since the start of rust/hg-cpython, an array of function pointers has several advantages: - it can hold several functions. That's our main motivation here. We plan to expose index_length() and index_node(), which will be needed for a Rust implementation of nodemap. - it could also have data - (probably minor in the case of Mercurial) proper support for architectures for which data and code pointers don't have the same size. Differential Revision: https://phab.mercurial-scm.org/D7543 diff -r 26cf356ae772 -r f384d68d8ea8 mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c Sun Dec 22 23:09:37 2019 -0500 +++ b/mercurial/cext/revlog.c Wed Nov 27 17:59:58 2019 +0100 @@ -37,6 +37,10 @@ int children[16]; } nodetreenode; +typedef struct { + int (*index_parents)(PyObject *, int, int *); +} Revlog_CAPI; + /* * A base-16 trie for fast node->rev mapping. * @@ -3032,6 +3036,10 @@ }; #endif /* WITH_RUST */ +static Revlog_CAPI CAPI = { + HgRevlogIndex_GetParents, +}; + void revlog_module_init(PyObject *mod) { PyObject *caps = NULL; @@ -3055,11 +3063,9 @@ if (nullentry) PyObject_GC_UnTrack(nullentry); - caps = PyCapsule_New(HgRevlogIndex_GetParents, - "mercurial.cext.parsers.index_get_parents_CAPI", - NULL); + caps = PyCapsule_New(&CAPI, "mercurial.cext.parsers.revlog_CAPI", NULL); if (caps != NULL) - PyModule_AddObject(mod, "index_get_parents_CAPI", caps); + PyModule_AddObject(mod, "revlog_CAPI", caps); #ifdef WITH_RUST rustlazyancestorsType.tp_new = PyType_GenericNew; diff -r 26cf356ae772 -r f384d68d8ea8 rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs Sun Dec 22 23:09:37 2019 -0500 +++ b/rust/hg-cpython/src/cindex.rs Wed Nov 27 17:59:58 2019 +0100 @@ -14,15 +14,18 @@ use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -py_capsule_fn!( - from mercurial.cext.parsers import index_get_parents_CAPI - as get_parents_capi - signature ( - index: *mut RawPyObject, - rev: c_int, - ps: *mut [c_int; 2], - ) -> c_int -); +#[repr(C)] +pub struct Revlog_CAPI { + index_parents: unsafe extern "C" fn( + index: *mut revlog_capi::RawPyObject, + rev: c_int, + ps: *mut [c_int; 2], + ) -> c_int, +} + +py_capsule!( + from mercurial.cext.parsers import revlog_CAPI + as revlog_capi for Revlog_CAPI); /// A `Graph` backed up by objects and functions from revlog.c /// @@ -58,14 +61,14 @@ /// mechanisms in other contexts. pub struct Index { index: PyObject, - parents: get_parents_capi::CapsuleFn, + capi: &'static Revlog_CAPI, } impl Index { pub fn new(py: Python, index: PyObject) -> PyResult { Ok(Index { index: index, - parents: get_parents_capi::retrieve(py)?, + capi: unsafe { revlog_capi::retrieve(py)? }, }) } } @@ -75,7 +78,7 @@ let guard = Python::acquire_gil(); Index { index: self.index.clone_ref(guard.python()), - parents: self.parents.clone(), + capi: self.capi, } } } @@ -88,7 +91,7 @@ } let mut res: [c_int; 2] = [0; 2]; let code = unsafe { - (self.parents)( + (self.capi.index_parents)( self.index.as_ptr(), rev as c_int, &mut res as *mut [c_int; 2],