Since there is no glue for go yet, I have to translate the roc-types to go for my platform manually. I was not able to do it for a tag with payload. For example
MyType : [Foo Str, Bar U64]
I would guess, that it first contains a Number, which Tag is active and then enough bytes for the biggest type (for example 24 byte for Str on a 64bit system or 8 byte for U64).
I also guess, that the type is on the stack and therefore does not need a refcount-prefix.
Are my assumptions correct?
For this to work in go, I have to write a .h
file. How would you define such a type in C
when the payload can be different types?
Sometimes I generate the glue for rust, and then compare notes... maybe that will help?
That helped. So the rust code looks like this:
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, )]
#[repr(u8)]
pub enum discriminant_MyType {
Bar = 0,
Foo = 1,
}
#[repr(C, align(8))]
pub union union_MyType {
Bar: u64,
Foo: core::mem::ManuallyDrop<roc_std::RocStr>,
}
#[repr(C)]
pub struct MyType {
payload: union_MyType,
discriminant: discriminant_MyType,
}
When I understand this correctly, then my guess was correct. But the u8 value, that tells the type, is after the value.
Yeah, tag is at the end cause it is more likely to fit in a gap instead of requiring alignment extra bytes.
It works :tada:
In the .h
file, it looks like this:
union MyTypeUnion {
struct RocStr foo;
long long unsigned int bar;
};
struct MyType {
union MyTypeUnion payload;
unsigned char discriminant;
};
This is not so helpful. Go converts a C-union to a byte-array, with enough space for the biggest type. So in this case [24]byte
.
The the following code was necessary, to get the actual payload:
switch mytype.discriminant {
case 0:
payload := *(*C.struct_RocStr)(unsafe.Pointer(&mytype.payload))
foo := rocStrRead(payload)
...
case 1:
payload := *(*C.longlong)(unsafe.Pointer(&mytype.payload))
bar := uint64(payload)
...
default:
panic("invalid payload")
}
Brendan Hansknecht said:
Yeah, tag is at the end cause it is more likely to fit in a gap instead of requiring alignment extra bytes.
This makes sense.
Last updated: Jul 05 2025 at 12:14 UTC