Skip to content

Commit 6fe4769

Browse files
authored
Merge pull request #257 from skade/opaque-types-fix
2 parents adca786 + 9081170 commit 6fe4769

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

src/ffi.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -740,8 +740,18 @@ void bar(struct Bar *arg);
740740
To do this in Rust, let’s create our own opaque types:
741741
742742
```rust
743-
#[repr(C)] pub struct Foo { _private: [u8; 0] }
744-
#[repr(C)] pub struct Bar { _private: [u8; 0] }
743+
#[repr(C)]
744+
pub struct Foo {
745+
_data: [u8; 0],
746+
_marker:
747+
core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
748+
}
749+
#[repr(C)]
750+
pub struct Bar {
751+
_data: [u8; 0],
752+
_marker:
753+
core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
754+
}
745755
746756
extern "C" {
747757
pub fn foo(arg: *mut Foo);
@@ -750,12 +760,12 @@ extern "C" {
750760
# fn main() {}
751761
```
752762

753-
By including a private field and no constructor,
763+
By including at least one private field and no constructor,
754764
we create an opaque type that we can't instantiate outside of this module.
755765
(A struct with no field could be instantiated by anyone.)
756766
We also want to use this type in FFI, so we have to add `#[repr(C)]`.
757-
And to avoid warning around using `()` in FFI, we instead use an empty array,
758-
which works just as well as an empty type but is FFI-compatible.
767+
The marker ensures the compiler does not mark the struct as `Send`, `Sync` and `Unpin` are
768+
not applied to the struct. (`*mut u8` is not `Send` or `Sync`, `PhantomPinned` is not `Unpin`)
759769

760770
But because our `Foo` and `Bar` types are
761771
different, we’ll get type safety between the two of them, so we cannot

0 commit comments

Comments
 (0)