Michael-F-Bryan / rust-ffi-guide

A guide for doing FFI using Rust
https://michael-f-bryan.github.io/rust-ffi-guide/
Creative Commons Zero v1.0 Universal
282 stars 18 forks source link

Rust Enums and Tagged Unions #54

Open Michael-F-Bryan opened 6 years ago

Michael-F-Bryan commented 6 years ago

This problem would pass a normal Rust enum to C++, where the C++ code has declared a tagged union which roughly matches how Rust does things internally.

The solution should mention that this is UB because an enum's internal representation is unspecified. Instead Rust should manually define a tagged union which is the equivalent of our enum, possibly adding the appropriate From<...> impls.

You'd need to explicitly write something like this:

#[derive(Copy, Clone)]
#[repr(C)]
struct Car {
    tag: CarType,
    value: CarValue,
}

#[derive(Copy, Clone)]
#[repr(C)]
union CarValue {
    fast: FastCar,
    slow: SlowCar,
}

#[derive(Copy, Clone, Debug)]
struct FastCar(u32);

#[derive(Copy, Clone, Debug)]
struct SlowCar(f64);

#[derive(Copy, Clone)]
#[repr(C)]
enum CarType {
    Fast,
    Slow,
}

As well as its C equivalent:

struct SlowCar{
  ...
}

struct FastCar{
  ...
}

union union_car {
  FastCar,
  SlowCar
}

enum Cartype{Slow,Fast};

struct Car{
  union_car inner;
  Cartype tag;
}