about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2015-08-11 13:26:45 +0530
committerManish Goregaokar <manishsmail@gmail.com>2015-08-11 16:48:01 +0530
commite40516bcb4e3538aca55e1276a9fe20cf2d63280 (patch)
treed2bb21a631b0bd0d1e116ca15320a767aa10d226
parent23f43896ce92830173e503eab8b2f7fba8137e37 (diff)
parent8c4dc18d2a51321070abccd34182381bdc66054d (diff)
downloadrust-e40516bcb4e3538aca55e1276a9fe20cf2d63280.tar.gz
rust-e40516bcb4e3538aca55e1276a9fe20cf2d63280.zip
Rollup merge of #27542 - steveklabnik:gh27303, r=alexcrichton
Fixes #27303
-rw-r--r--src/doc/trpl/ffi.md53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md
index 753a5a32e8a..878947e10ad 100644
--- a/src/doc/trpl/ffi.md
+++ b/src/doc/trpl/ffi.md
@@ -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()`.