Michael-F-Bryan/rust-ffi-guide

Rust Enums and Tagged Unions

Michael-F-Bryan opened this issue · 0 comments

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;
}