Skip to content

Commit

Permalink
Rollup merge of rust-lang#27542 - steveklabnik:gh27303, r=alexcrichton
Browse files Browse the repository at this point in the history
  • Loading branch information
Manishearth committed Aug 11, 2015
2 parents 23f4389 + 8c4dc18 commit e40516b
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions src/doc/trpl/ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -555,3 +555,56 @@ pub extern fn oh_no() -> i32 {
# fn main() {}
```

# Representing opaque structs

Sometimes, a C library wants to provide a pointer to something, but not let you
know the internal details of the thing it wants. The simplest way is to use a
`void *` argument:

```c
void foo(void *arg);
void bar(void *arg);
```
We can represent this in Rust with the `c_void` type:
```rust
# #![feature(libc)]
extern crate libc;
extern "C" {
pub fn foo(arg: *mut libc::c_void);
pub fn bar(arg: *mut libc::c_void);
}
# fn main() {}
```

This is a perfectly valid way of handling the situation. However, we can do a bit
better. To solve this, some C libraries will instead create a `struct`, where
the details and memory layout of the struct are private. This gives some amount
of type safety. These structures are called ‘opaque’. Here’s an example, in C:

```c
struct Foo; /* Foo is a structure, but its contents are not part of the public interface */
struct Bar;
void foo(struct Foo *arg);
void bar(struct Bar *arg);
```
To do this in Rust, let’s create our own opaque types with `enum`:
```rust
pub enum Foo {}
pub enum Bar {}
extern "C" {
pub fn foo(arg: *mut Foo);
pub fn bar(arg: *mut Bar);
}
# fn main() {}
```

By using an `enum` with no variants, we create an opaque type that we can’t
instantiate, as it has no variants. But because our `Foo` and `Bar` types are
different, we’ll get type safety between the two of them, so we cannot
accidentally pass a pointer to `Foo` to `bar()`.

0 comments on commit e40516b

Please sign in to comment.