What Rust idiom defines a field that points to an opaque C pointer?

Given the structure:

#[repr(C)]
pub struct User {
    pub name: *const c_char,
    pub age: u8,
    pub ctx: ??,
}

      

the field ctx

will be processed only by the C code; it is a pointer to a C struct UserAttr

.

According to the Rust RFI documentation , the selection will be defined as an opaque type pub enum UserAttr {}

. However, I found that Rust cannot copy its value for example. why the address of the object is changed using methods .

What's the correct way in Rust to define such an opaque pointer so that its value (as a pointer) is copied through methods?

0


source to share


1 answer


The documentation doesn't lie to you:

To do this in Rust, create your own opaque types with enum

:

pub enum Foo {}
pub enum Bar {}

extern "C" {
    pub fn foo(arg: *mut Foo);
    pub fn bar(arg: *mut Bar);
}

      

By using enum

no variants, we create an opaque type, which we cannot be instantiated as it has no variants. But since ours Foo

and Bar

types are different, it's good to get type safety between them, so we can't accidentally pass a pointer Foo

to bar()

.

A transparent pointer is usually enum Foo {}

because there is no normal way to create this type. You can create pointers to it.

mod ffi {
    use std::ptr;

    pub enum MyTypeFromC {}

    pub fn constructor() -> *mut MyTypeFromC {
        ptr::null_mut()
    }

    pub fn something(_thing: *mut MyTypeFromC) {
        println!("Doing a thing");
    }
}

use ffi::*;

struct MyRustType {
    score: u8,
    the_c_thing: *mut MyTypeFromC,
}

impl MyRustType {
    fn new() -> MyRustType {
        MyRustType {
            score: 42,
            the_c_thing: constructor(),
        }
    }

    fn something(&mut self) {
        println!("My score is {}", self.score);
        ffi::something(self.the_c_thing);
        self.score += 1;
    }
}

fn main() {
    let mut my_thing = MyRustType::new();
    my_thing.something();
}

      

A bit to break:



// opaque -----V~~~~~~~~~V
          *mut MyTypeFromC
//        ^~~^ ------------ pointer

      

Thus, it is an opaque pointer. Moving the structure MyRustType

will not change the pointer value.


RFC 1861 introduced the outer type concept. Although implemented, it has not yet stabilized. Once that happens, this becomes the preferred implementation:

#![feature(extern_types)]

extern "C" {
    type Foo;
}

type FooPtr = *mut Foo;

      

+4


source







All Articles