Re: [PATCH 2 of 5 RFC] rust: iterator bindings to C code
> On Jan 16, 2019, at 11:13, Georges Racinet > wrote: > > Hi Augie, > > On 10/1/18 5:02 PM, Augie Fackler wrote: >> On Fri, Sep 28, 2018 at 03:31:09PM +0200, Georges Racinet wrote: >>> # HG changeset patch >>> # User Georges Racinet >>> # Date 1538059896 -7200 >>> # Thu Sep 27 16:51:36 2018 +0200 >>> # Node ID de88c09512565ed1c12e2ff9159e06ed8d762d15 >>> # Parent d8c9571755a64e1fc3429587dfd3949b9862eceb >>> # EXP-Topic rustancestors-rfc >>> rust: iterator bindings to C code >>> >>> In this changeset, still made of Rust code only, >>> we expose the Rust iterator for instantiation and >>> consumption from C code. >>> >>> The idea is that both the index and index_get_parents() >>> will be passed from the C extension, hence avoiding a hard >>> link dependency to parsers.so, so that the crate can >>> still be built and tested independently. >>> >>> On the other hand, parsers.so will use the symbols >>> defined in this changeset. >>> >>> diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.lock >>> --- a/mercurial/rust/Cargo.lock Thu Sep 27 17:03:16 2018 +0200 >>> +++ b/mercurial/rust/Cargo.lock Thu Sep 27 16:51:36 2018 +0200 >>> @@ -1,4 +1,14 @@ >>> [[package]] >>> name = "hgancestors" >>> version = "0.1.0" >>> +dependencies = [ >>> + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", >>> +] >>> >>> +[[package]] >>> +name = "libc" >>> +version = "0.2.43" >>> +source = "registry+https://github.com/rust-lang/crates.io-index; >>> + >>> +[metadata] >>> +"checksum libc 0.2.43 >>> (registry+https://github.com/rust-lang/crates.io-index)" = >>> "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" >>> diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.toml >>> --- a/mercurial/rust/Cargo.toml Thu Sep 27 17:03:16 2018 +0200 >>> +++ b/mercurial/rust/Cargo.toml Thu Sep 27 16:51:36 2018 +0200 >>> @@ -2,3 +2,9 @@ >>> name = "hgancestors" >>> version = "0.1.0" >>> authors = ["Georges Racinet "] >>> + >>> +[dependencies] >>> +libc = "*" >>> + >>> +[lib] >>> +crate-type = ["dylib"] >>> diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/src/cpython.rs >>> --- /dev/null Thu Jan 01 00:00:00 1970 + >>> +++ b/mercurial/rust/src/cpython.rs Thu Sep 27 16:51:36 2018 +0200 >>> @@ -0,0 +1,170 @@ >>> +// Copyright 2018 Georges Racinet >>> +// >>> +// This software may be used and distributed according to the terms of the >>> +// GNU General Public License version 2 or any later version. >>> + >>> +//! Bindings for CPython extension code >> This looks like you're using cffi and not cpython extension logic? I >> don't see anything python-specific in here, so maybe this is misnamed? > This patch is outdated, and the corresponding code has been moved during > the October sprint in its own crate, rust/hg-direct-ffi, before Yuya > queued it. Ugh, I did something dumb on my laptop and a bunch of zombie messages got sent today. Sorry! ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 5 RFC] rust: iterator bindings to C code
Hi Augie, On 10/1/18 5:02 PM, Augie Fackler wrote: > On Fri, Sep 28, 2018 at 03:31:09PM +0200, Georges Racinet wrote: >> # HG changeset patch >> # User Georges Racinet >> # Date 1538059896 -7200 >> # Thu Sep 27 16:51:36 2018 +0200 >> # Node ID de88c09512565ed1c12e2ff9159e06ed8d762d15 >> # Parent d8c9571755a64e1fc3429587dfd3949b9862eceb >> # EXP-Topic rustancestors-rfc >> rust: iterator bindings to C code >> >> In this changeset, still made of Rust code only, >> we expose the Rust iterator for instantiation and >> consumption from C code. >> >> The idea is that both the index and index_get_parents() >> will be passed from the C extension, hence avoiding a hard >> link dependency to parsers.so, so that the crate can >> still be built and tested independently. >> >> On the other hand, parsers.so will use the symbols >> defined in this changeset. >> >> diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.lock >> --- a/mercurial/rust/Cargo.lock Thu Sep 27 17:03:16 2018 +0200 >> +++ b/mercurial/rust/Cargo.lock Thu Sep 27 16:51:36 2018 +0200 >> @@ -1,4 +1,14 @@ >> [[package]] >> name = "hgancestors" >> version = "0.1.0" >> +dependencies = [ >> + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", >> +] >> >> +[[package]] >> +name = "libc" >> +version = "0.2.43" >> +source = "registry+https://github.com/rust-lang/crates.io-index; >> + >> +[metadata] >> +"checksum libc 0.2.43 >> (registry+https://github.com/rust-lang/crates.io-index)" = >> "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" >> diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.toml >> --- a/mercurial/rust/Cargo.toml Thu Sep 27 17:03:16 2018 +0200 >> +++ b/mercurial/rust/Cargo.toml Thu Sep 27 16:51:36 2018 +0200 >> @@ -2,3 +2,9 @@ >> name = "hgancestors" >> version = "0.1.0" >> authors = ["Georges Racinet "] >> + >> +[dependencies] >> +libc = "*" >> + >> +[lib] >> +crate-type = ["dylib"] >> diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/src/cpython.rs >> --- /dev/nullThu Jan 01 00:00:00 1970 + >> +++ b/mercurial/rust/src/cpython.rs Thu Sep 27 16:51:36 2018 +0200 >> @@ -0,0 +1,170 @@ >> +// Copyright 2018 Georges Racinet >> +// >> +// This software may be used and distributed according to the terms of the >> +// GNU General Public License version 2 or any later version. >> + >> +//! Bindings for CPython extension code > This looks like you're using cffi and not cpython extension logic? I > don't see anything python-specific in here, so maybe this is misnamed? This patch is outdated, and the corresponding code has been moved during the October sprint in its own crate, rust/hg-direct-ffi, before Yuya queued it. > > If I've misread this, why this route rather than using the cpython > crate, so that the `unsafe` code is consolidated into one package? This is indeed the way forward that's been adopted since then (see rust/hg-cpython). I believe there was a rationale for this choice in one of the changesets of the series. The TL;DR would be that it wasn't clear at that time how Rust code could call index_get_parents() from parsers.c [1] and that it could be done without choosing between the three options presented in the Oxidation wiki page (namely rust-cpython, pyo3 and cffi), something I wasn't at ease with before meeting other developers IRL. Now it is expected that hg-direct-ffi will die in some not-too-far future. Hope this helps, [1] now it is, this is what PyCapsule is meant for, but I discovered it later, also during the October sprint. As a side note, I have a currently a PR about it in rust-cpython which will reduce the amount of unsafe code in hg-cpython if I can make it land. -- Georges Racinet https://octobus.net GPG: BF5456F4DC625443849B6E58EE20CA44EF691D39, sur serveurs publics signature.asc Description: OpenPGP digital signature ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 5 RFC] rust: iterator bindings to C code
On Fri, Sep 28, 2018 at 03:31:09PM +0200, Georges Racinet wrote: > # HG changeset patch > # User Georges Racinet > # Date 1538059896 -7200 > # Thu Sep 27 16:51:36 2018 +0200 > # Node ID de88c09512565ed1c12e2ff9159e06ed8d762d15 > # Parent d8c9571755a64e1fc3429587dfd3949b9862eceb > # EXP-Topic rustancestors-rfc > rust: iterator bindings to C code > > In this changeset, still made of Rust code only, > we expose the Rust iterator for instantiation and > consumption from C code. > > The idea is that both the index and index_get_parents() > will be passed from the C extension, hence avoiding a hard > link dependency to parsers.so, so that the crate can > still be built and tested independently. > > On the other hand, parsers.so will use the symbols > defined in this changeset. > > diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.lock > --- a/mercurial/rust/Cargo.lock Thu Sep 27 17:03:16 2018 +0200 > +++ b/mercurial/rust/Cargo.lock Thu Sep 27 16:51:36 2018 +0200 > @@ -1,4 +1,14 @@ > [[package]] > name = "hgancestors" > version = "0.1.0" > +dependencies = [ > + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", > +] > > +[[package]] > +name = "libc" > +version = "0.2.43" > +source = "registry+https://github.com/rust-lang/crates.io-index; > + > +[metadata] > +"checksum libc 0.2.43 > (registry+https://github.com/rust-lang/crates.io-index)" = > "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" > diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.toml > --- a/mercurial/rust/Cargo.toml Thu Sep 27 17:03:16 2018 +0200 > +++ b/mercurial/rust/Cargo.toml Thu Sep 27 16:51:36 2018 +0200 > @@ -2,3 +2,9 @@ > name = "hgancestors" > version = "0.1.0" > authors = ["Georges Racinet "] > + > +[dependencies] > +libc = "*" > + > +[lib] > +crate-type = ["dylib"] > diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/src/cpython.rs > --- /dev/null Thu Jan 01 00:00:00 1970 + > +++ b/mercurial/rust/src/cpython.rs Thu Sep 27 16:51:36 2018 +0200 > @@ -0,0 +1,170 @@ > +// Copyright 2018 Georges Racinet > +// > +// This software may be used and distributed according to the terms of the > +// GNU General Public License version 2 or any later version. > + > +//! Bindings for CPython extension code This looks like you're using cffi and not cpython extension logic? I don't see anything python-specific in here, so maybe this is misnamed? If I've misread this, why this route rather than using the cpython crate, so that the `unsafe` code is consolidated into one package? > +//! > +//! This exposes methods to build and use a `rustlazyancestors` iterator > +//! from C code, using an index and its parents function that are passed > +//! from the caller at instantiation. > + > +extern crate libc; > + > +use std::boxed::Box; > +use self::libc::{c_void, c_int, ssize_t}; > +use super::ancestors::{Graph, AncestorsIterator}; > + > +type IndexPtr = *mut c_void; > +type IndexParentsFn = extern "C" fn(index: IndexPtr, > +rev: ssize_t, > +ps: *mut [c_int; 2], > +max_rev: c_int) > +-> c_int; > + > +/// A Graph backed up by objects and functions from revlog.c > +/// > +/// This implementation of the Graph trait, relies on (pointers to) > +/// - the C index object (`index` member) > +/// - the `index_get_parents()` function (`parents` member) > +pub struct Index { > +index: IndexPtr, > +parents: IndexParentsFn, > +} > + > +impl Index { > +pub fn new(index: IndexPtr, parents: IndexParentsFn) -> Self { > +Index { > +index: index, > +parents: parents, > +} > +} > +} > + > +impl Graph for Index { > +/// wrap a call to the C extern parents function > +fn parents(, rev: i32) -> (i32, i32) { > +let mut res: [c_int; 2] = [0; 2]; > +// surprisingly the call below is not unsafe, whereas calling the > +// same extern function directly (not through a pointer) would. > +// Maybe that depends on rustc version, though. > +let code = (self.parents)( > +self.index, > +rev as ssize_t, > + res as *mut [c_int; 2], > +rev, > +); > +if code != 0 { > +// TODO panic! and FFI don't get well together > +panic!("Corrupted index"); > +} > +(res[0], res[1]) > +} > +} > + > +/// Wrapping of AncestorsIterator constructor, for C callers. > +/// > +/// Besides `initrevs`, `stoprev` and `inclusive`, that are converted > +/// we receive the index and the parents function as pointers > +#[no_mangle] > +pub extern "C" fn rustlazyancestors_init( > +index: IndexPtr, > +parents: IndexParentsFn, > +initrevslen: usize, > +initrevs: *mut i64, > +stoprev: i64, > +inclusive: i64, > +) -> *mut AncestorsIterator { > +let v: Vec = > +
Re: [PATCH 2 of 5 RFC] rust: iterator bindings to C code
On 9/30/18 5:46 AM, Yuya Nishihara wrote: > On Fri, 28 Sep 2018 15:31:09 +0200, Georges Racinet wrote: >> # HG changeset patch >> # User Georges Racinet >> # Date 1538059896 -7200 >> # Thu Sep 27 16:51:36 2018 +0200 >> # Node ID de88c09512565ed1c12e2ff9159e06ed8d762d15 >> # Parent d8c9571755a64e1fc3429587dfd3949b9862eceb >> # EXP-Topic rustancestors-rfc >> rust: iterator bindings to C code >> >> In this changeset, still made of Rust code only, >> we expose the Rust iterator for instantiation and >> consumption from C code. >> >> The idea is that both the index and index_get_parents() >> will be passed from the C extension, hence avoiding a hard >> link dependency to parsers.so, so that the crate can >> still be built and tested independently. > Just a note. That means parents() can't take hidden revisions into account. > We might have to filter out hidden revisions from the initial set. Yes, that's the plan. > > Another idea is to scan the revlog index in pure Rust. That's fairly easy > since each revlog entry is fixed sized unless data is inlined. I'm sure > there are several revlog parsers written by Mecurial folks to learn Rust. > I have one. :) I'd love to see it and agree that hooking onto such a parser could be seen as a longer term perspective for what we're doing incrementally here. On the other hand, I dismissed the idea to implement index_get_parents() in Rust over the index C data structure as a bit too complicated, as it seems to involve Python objects, and hence would require the help of rust-cpython or a similar library. > >> +use std::boxed::Box; > Nit: it's included in prelude. Noted > >> +type IndexPtr = *mut c_void; >> +type IndexParentsFn = extern "C" fn(index: IndexPtr, >> +rev: ssize_t, >> +ps: *mut [c_int; 2], >> +max_rev: c_int) >> +-> c_int; > ... > >> +impl Graph for Index { >> +/// wrap a call to the C extern parents function >> +fn parents(, rev: i32) -> (i32, i32) { >> +let mut res: [c_int; 2] = [0; 2]; >> +// surprisingly the call below is not unsafe, whereas calling the >> +// same extern function directly (not through a pointer) would. >> +// Maybe that depends on rustc version, though. >> +let code = (self.parents)( > Perhaps, the IndexParentsFn type has to be labeled as "unsafe fn". Ah yes, you're right, it works. The fact is, with a function pointer, the Rust compiler can't know whether it's from external code or just meant for external usage, should have thought of that. > >> +/// Wrapping of AncestorsIterator constructor, for C callers. >> +/// >> +/// Besides `initrevs`, `stoprev` and `inclusive`, that are converted >> +/// we receive the index and the parents function as pointers >> +#[no_mangle] >> +pub extern "C" fn rustlazyancestors_init( >> +index: IndexPtr, >> +parents: IndexParentsFn, >> +initrevslen: usize, >> +initrevs: *mut i64, >> +stoprev: i64, >> +inclusive: i64, >> +) -> *mut AncestorsIterator { >> +let v: Vec = >> +unsafe { Vec::from_raw_parts(initrevs, initrevslen, initrevslen) }; > It's probably wrong to construct a Vec from a memory not allocated in Rust. > Rust uses specialized malloc() variants. IIRC, the default is jemalloc and > Vec has some other optimizations. Yes, you're right, it makes much more sense to abide by the rule that memory allocated by one language should be freed by the same one. Given that and your earlier comments, I'll probably submit a new version where rustlazyancestors_init() makes an iterator over revision numbers (ie, i32) out of the initrevs it receives and pass it to AncestorsIterator::new(). The raw pointer (initrevs array) will then be freed from the C caller. Also need to replace all occurrences of i64 by c_long for platform independence. Thanks for the comments, -- Georges Racinet Anybox SAS, http://anybox.fr Téléphone: +33 6 51 32 07 27 GPG: B59E 22AB B842 CAED 77F7 7A7F C34F A519 33AB 0A35, sur serveurs publics ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 5 RFC] rust: iterator bindings to C code
On Fri, 28 Sep 2018 15:31:09 +0200, Georges Racinet wrote: > # HG changeset patch > # User Georges Racinet > # Date 1538059896 -7200 > # Thu Sep 27 16:51:36 2018 +0200 > # Node ID de88c09512565ed1c12e2ff9159e06ed8d762d15 > # Parent d8c9571755a64e1fc3429587dfd3949b9862eceb > # EXP-Topic rustancestors-rfc > rust: iterator bindings to C code > > In this changeset, still made of Rust code only, > we expose the Rust iterator for instantiation and > consumption from C code. > > The idea is that both the index and index_get_parents() > will be passed from the C extension, hence avoiding a hard > link dependency to parsers.so, so that the crate can > still be built and tested independently. Just a note. That means parents() can't take hidden revisions into account. We might have to filter out hidden revisions from the initial set. Another idea is to scan the revlog index in pure Rust. That's fairly easy since each revlog entry is fixed sized unless data is inlined. I'm sure there are several revlog parsers written by Mecurial folks to learn Rust. I have one. :) > +use std::boxed::Box; Nit: it's included in prelude. > +type IndexPtr = *mut c_void; > +type IndexParentsFn = extern "C" fn(index: IndexPtr, > +rev: ssize_t, > +ps: *mut [c_int; 2], > +max_rev: c_int) > +-> c_int; ... > +impl Graph for Index { > +/// wrap a call to the C extern parents function > +fn parents(, rev: i32) -> (i32, i32) { > +let mut res: [c_int; 2] = [0; 2]; > +// surprisingly the call below is not unsafe, whereas calling the > +// same extern function directly (not through a pointer) would. > +// Maybe that depends on rustc version, though. > +let code = (self.parents)( Perhaps, the IndexParentsFn type has to be labeled as "unsafe fn". > +/// Wrapping of AncestorsIterator constructor, for C callers. > +/// > +/// Besides `initrevs`, `stoprev` and `inclusive`, that are converted > +/// we receive the index and the parents function as pointers > +#[no_mangle] > +pub extern "C" fn rustlazyancestors_init( > +index: IndexPtr, > +parents: IndexParentsFn, > +initrevslen: usize, > +initrevs: *mut i64, > +stoprev: i64, > +inclusive: i64, > +) -> *mut AncestorsIterator { > +let v: Vec = > +unsafe { Vec::from_raw_parts(initrevs, initrevslen, initrevslen) }; It's probably wrong to construct a Vec from a memory not allocated in Rust. Rust uses specialized malloc() variants. IIRC, the default is jemalloc and Vec has some other optimizations. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 5 RFC] rust: iterator bindings to C code
# HG changeset patch # User Georges Racinet # Date 1538059896 -7200 # Thu Sep 27 16:51:36 2018 +0200 # Node ID de88c09512565ed1c12e2ff9159e06ed8d762d15 # Parent d8c9571755a64e1fc3429587dfd3949b9862eceb # EXP-Topic rustancestors-rfc rust: iterator bindings to C code In this changeset, still made of Rust code only, we expose the Rust iterator for instantiation and consumption from C code. The idea is that both the index and index_get_parents() will be passed from the C extension, hence avoiding a hard link dependency to parsers.so, so that the crate can still be built and tested independently. On the other hand, parsers.so will use the symbols defined in this changeset. diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.lock --- a/mercurial/rust/Cargo.lock Thu Sep 27 17:03:16 2018 +0200 +++ b/mercurial/rust/Cargo.lock Thu Sep 27 16:51:36 2018 +0200 @@ -1,4 +1,14 @@ [[package]] name = "hgancestors" version = "0.1.0" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", +] +[[package]] +name = "libc" +version = "0.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index; + +[metadata] +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/Cargo.toml --- a/mercurial/rust/Cargo.toml Thu Sep 27 17:03:16 2018 +0200 +++ b/mercurial/rust/Cargo.toml Thu Sep 27 16:51:36 2018 +0200 @@ -2,3 +2,9 @@ name = "hgancestors" version = "0.1.0" authors = ["Georges Racinet "] + +[dependencies] +libc = "*" + +[lib] +crate-type = ["dylib"] diff -r d8c9571755a6 -r de88c0951256 mercurial/rust/src/cpython.rs --- /dev/null Thu Jan 01 00:00:00 1970 + +++ b/mercurial/rust/src/cpython.rs Thu Sep 27 16:51:36 2018 +0200 @@ -0,0 +1,170 @@ +// Copyright 2018 Georges Racinet +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +//! Bindings for CPython extension code +//! +//! This exposes methods to build and use a `rustlazyancestors` iterator +//! from C code, using an index and its parents function that are passed +//! from the caller at instantiation. + +extern crate libc; + +use std::boxed::Box; +use self::libc::{c_void, c_int, ssize_t}; +use super::ancestors::{Graph, AncestorsIterator}; + +type IndexPtr = *mut c_void; +type IndexParentsFn = extern "C" fn(index: IndexPtr, +rev: ssize_t, +ps: *mut [c_int; 2], +max_rev: c_int) +-> c_int; + +/// A Graph backed up by objects and functions from revlog.c +/// +/// This implementation of the Graph trait, relies on (pointers to) +/// - the C index object (`index` member) +/// - the `index_get_parents()` function (`parents` member) +pub struct Index { +index: IndexPtr, +parents: IndexParentsFn, +} + +impl Index { +pub fn new(index: IndexPtr, parents: IndexParentsFn) -> Self { +Index { +index: index, +parents: parents, +} +} +} + +impl Graph for Index { +/// wrap a call to the C extern parents function +fn parents(, rev: i32) -> (i32, i32) { +let mut res: [c_int; 2] = [0; 2]; +// surprisingly the call below is not unsafe, whereas calling the +// same extern function directly (not through a pointer) would. +// Maybe that depends on rustc version, though. +let code = (self.parents)( +self.index, +rev as ssize_t, + res as *mut [c_int; 2], +rev, +); +if code != 0 { +// TODO panic! and FFI don't get well together +panic!("Corrupted index"); +} +(res[0], res[1]) +} +} + +/// Wrapping of AncestorsIterator constructor, for C callers. +/// +/// Besides `initrevs`, `stoprev` and `inclusive`, that are converted +/// we receive the index and the parents function as pointers +#[no_mangle] +pub extern "C" fn rustlazyancestors_init( +index: IndexPtr, +parents: IndexParentsFn, +initrevslen: usize, +initrevs: *mut i64, +stoprev: i64, +inclusive: i64, +) -> *mut AncestorsIterator { +let v: Vec = +unsafe { Vec::from_raw_parts(initrevs, initrevslen, initrevslen) }; +let inclb = match inclusive { +0 => false, +1 => true, +_ => panic!("Did not understand boolean FFI convention"), +}; + +Box::into_raw(Box::new(AncestorsIterator::new( +Index::new(index, parents), +, +stoprev, +inclb, +))) +} + +/// Deallocator to be called from C code +#[no_mangle] +pub extern "C" fn rustlazyancestors_drop( +raw_iter: *mut AncestorsIterator, +) { +unsafe { +Box::from_raw(raw_iter); +} +} + +/// Iteration main method to be called from C code