Skip to content

Help with enum of Box through FFI #64033

Closed
@marmeladema

Description

@marmeladema

Hello everyone!

I am having an issue understanding how to share an Enum, where some variants holds a Box, through FFI boundary.
The Enum looks like this:

#[derive(Debug)]
#[repr(C)]
pub enum SchemeType {
    Ip,
    Bytes,
    Int,
    Bool,
    Array(Box<SchemeType>),
    Map(Box<SchemeType>),
}

At the beginning I thought it would not possible to share this type with C directly, but then I found https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md
So after reading that RFC, I thought that the C type equivalent type would be something like:

typedef enum {
    SCHEME_TYPE_TAG_IP,
    SCHEME_TYPE_TAG_BYTES,
    SCHEME_TYPE_TAG_INT,
    SCHEME_TYPE_TAG_BOOL,
    SCHEME_TYPE_TAG_ARRAY,
    SCHEME_TYPE_TAG_MAP,
} scheme_type_tag_t;

typedef struct {
    scheme_type_tag_t tag;
    void *data;
} scheme_type_t;

You can find the code here: marmeladema/rust-ffi-enum-box@8d61450

This did not worked well, and crashed in the test functions with Illegal instruction.
I read this issue #52976 but its still not clear at all if Box<T> can be represented directly with a pointer. Its currently not #[repr(transparent)] so I guess until it is, it cannot safely be done.

After trying different things, i figured that adding 8 bytes padding to the end of scheme_type_t worked, at least on x86_64: marmeladema/rust-ffi-enum-box@2bc030e

But this does not work at all on aarch64.

The question is then, how should I approach this issue?
I figured the best way might be add a FFI-compatible SchemeTypeFFI wrapper, (storing a raw pointer instead of a Box<T> and convert back and forth from and to real Rust SchemeType type:

pub enum SchemeTypeFFI {
    Ip,
    Bytes,
    Int,
    Bool,
    Array(*mut SchemeType),
    Map(*mut SchemeType),
}

Thank you in advance for your help!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions