How can I open a secure wrapper around belonging to a pointer?

I am wrapping a C library that has two structures: one has a pointer to the other.

struct StructA {
    void * some_mem;
};

struct StructB {
    void * some_mem;
    struct StructA * some_struct;
};

Both of these structures have their own memory, so my shell has constructors and destructors for both.

struct StructA(*mut c_void);

impl StructA {
    fn new() -> Self {
        StructA(c_constructor())
    }
}

impl Drop for StructA {
    fn drop(&mut self) {
        let StructA(ptr) = self;
        c_destructor(ptr);
    }
}

There is also a function that takes a pointer to StructBand returns a pointer to StructA:

const struct StructA * get_struct(const struct StructB * obj);

The user of this function should not release the returned pointer, since it will be released when the user releases obj.

? , StructB , StructA. , get_struct , StructA (?). , ?

StructA , , , , .

+4
2

StructA , , , .

. StructA * StructA * , a Box<T> a &T. " ", .

- , , :

use std::marker::PhantomData;
struct OwnedA(*mut c_void);
impl Drop for OwnedA {
    fn drop(&mut self) { }
}
impl OwnedA {
    fn deref(&self) -> RefA { RefA(self.0, PhantomData) }
}
struct RefA<'a>(*mut c_void, PhantomData<&'a u8>);

struct OwnedB(*mut c_void);

impl Drop for OwnedB {
    fn drop(&mut self) { }
}

impl OwnedB {
    fn get_a(&self) -> RefA { RefA(get_struct(self.0), PhantomData) }
}

, , lifetime RefA , RefA .

+4

StructA , , , .

, . , Rust. &str String, &[T] Vec<T>, Path PathBuf, , , , .

, , Deref DerefMut :

use std::ops::{Deref, DerefMut};

enum RawFoo {}

fn c_foo_new() -> *const RawFoo { std::ptr::null() }
fn c_foo_free(_f: *const RawFoo) {}
fn c_foo_count(_f: *const RawFoo) -> u8 { 42 }
fn c_foo_make_awesome(_f: *const RawFoo, _v: bool) { }

struct OwnedFoo(Foo);

impl OwnedFoo {
    fn new() -> OwnedFoo {
        OwnedFoo(Foo(c_foo_new()))
    }
}

impl Drop for OwnedFoo {
    fn drop(&mut self) { c_foo_free((self.0).0) }
}

impl Deref for OwnedFoo {
    type Target = Foo;
    fn deref(&self) -> &Self::Target { &self.0 }
}

impl DerefMut for OwnedFoo {
    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}

struct Foo(*const RawFoo);

impl Foo {
    fn count(&self) -> u8 { c_foo_count(self.0) }
    fn make_awesome(&mut self, v: bool) { c_foo_make_awesome(self.0, v) }
}

fn main() {
    let mut f = OwnedFoo::new();
    println!("{}", f.count());
    f.make_awesome(true);
}

, , &Foo:

use std::mem;

fn c_bar_foo_ref() -> *const RawFoo { std::ptr::null() }

// Ignoring boilerplate for wrapping the raw Bar pointer 
struct Bar;

impl Bar {
    fn new() -> Bar { Bar }

    fn foo(&self) -> &Foo {
        unsafe { mem::transmute(c_bar_foo_ref()) }
    }

    fn foo_mut(&mut self) -> &mut Foo {
        unsafe { mem::transmute(c_bar_foo_ref()) }
    }
}

fn main() {
    let mut b = Bar::new();
    println!("{}", b.foo().count());
    b.foo_mut().make_awesome(true);

    // Doesn't work - lifetime constrained to Bar
    // let nope = Bar::new().foo();
}
+2

All Articles