In cases like this the normal thing to do is to make the C structures
private and expose an abstract interface. Check out my zeromq binding, it
might be helpful:

https://github.com/erickt/rust-zmq/blob/master/zmq.rc

In your case with xmlParseFile, I would suggest not returning a pointer at
all, but return an value with the C structure hidden inside of it with a
destructor to free any memory associated with it. That will allow someone
to mutate it or store it into various boxes:

let mut doc1 = xmlParseFile("text.xml");
let doc2 = ~xmlParseFile("text.xml");
let doc3 = @mut xmlParseFile("text.xml");



On Sat, May 25, 2013 at 5:04 AM, Thomas Leonard <tal...@gmail.com> wrote:

> On 25 May 2013 12:03, Benjamin Herr <b...@0x539.de> wrote:
> > On Sat, 2013-05-25 at 11:09 +0100, Thomas Leonard wrote:
> >> Hi,
> >
> > Hi!
> >
> >> I'm trying to interface to some C code which uses a lot of structs. I
> >> can declare these using raw pointers, but then I lose the benefits of
> >> Rust's compile-time pointer checking. So I tried replacing the raw
> >> pointers with owned pointers, which more accurately captures the
> >> meaning of the C interface. But when I do this, the pointers get
> >> offset by 32 bytes.
> >>
> >> [...]
> >
> > Yeah, there's currently some overhead for owned boxes. From what I
> > understand, they share the structure of the refcounted managed boxes
> > with most of the fields nulled out (there's a struct to that effect in
> > https://github.com/mozilla/rust/blob/incoming/src/libstd/managed.rs#L17
> > I believe).
> >
> > I figure this is because managed boxes were there first, and owned boxes
> > kind of grew out of them, and this is going to change eventually when
> > someone gets around to it...
>
> Oh, OK.
>
> >> For example, I'd like to replace this:
> >>
> >> struct xmlNode {
> >>     name:     *i8,
> >>     ...
> >> }
> >>
> >> with:
> >>
> >> struct CString;
> >>
> >> struct xmlNode {
> >>     name:     ~CString,
> >>     ...
> >> }
> >>
> >> Then I could (I assume) define safe functions on my CString type (len,
> >> eq, etc) and not have to worry about memory leaks, etc when using them
> >> from safe code.
> >>
> >> Is this possible?
> >
> > I don't believe this is possible in general even accounting for the box
> > headers somehow because rust isn't promising what malloc/free
> > implementation it is using for owned pointers.
>
> Wouldn't that be up to the constructor/finalizer for CString (if any)?
>
> But in this case, the way you use the API is:
>
>         let doc: ~XmlDoc = xmlParseFile("test.xml");
>         let cur: &xmlNode = xmlDocGetRootElement(doc);
>
> XmlDoc is a Rust struct which wraps the C one, freeing the whole
> document when done. xmlNode is the actual C struct.
>
> So you never get a ~xmlNode, just a borrowed &xmlNode, and therefore
> Rust should never try to free any items that were allocated by the C
> library. Code using the library should be able to explore the tree
> freely within the lifetime of the borrowed root node, I think.
>
> On the other hand, providing mutable access might require a different
> API. If CString had constructors and destructors then they could
> ensure that they used malloc/free, and maybe then allow direct access
> to the C struct. Or maybe all mutations should go via wrapper
> functions.
>
> > Maybe someone else has a better idea, but you could wrap the unsafe
> > pointer into a struct with a safe interface and an impl for the Drop
> > trait that calls libc's free() for much the same semantics, if a bit
> > more awkward syntax. I think a type like this ought to be in libextra at
> > some point, but I don't think there is yet.
> >
> > https://github.com/mozilla/rust/blob/incoming/src/libextra/rc.rs does
> > something similar with refcounting instead of unique ownership
> > semantics, maybe that's a starting point.
>
>
> Thanks,
>
> --
> Dr Thomas Leonard        http://0install.net/
> GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
> GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA
> _______________________________________________
> Rust-dev mailing list
> Rust-dev@mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to