Closed flibitijibibo closed 1 month ago
For now you can replace all the public bool
in struct definitions with public byte
, and then adapt code or add property accessors. MarshalAs might work though, but I think it may not fix pointers-to-T, only out and ref.
Will push the workaround soon!
if this is only necessary for struct blitting, we could reduce the blast radius of the workaround by only mapping _Bool
to byte
when the TypeContext
is StructField
I should point out that while MarshalAs in the struct may work, it won't work for WebAssembly .NET right now, which may actually matter to someone. This is because the marshaling implementation for WASM is much simpler than the one for other targets.
if this is only necessary for struct blitting, we could reduce the blast radius of the workaround by only mapping
_Bool
tobyte
when theTypeContext
isStructField
Another option we could try would be to generate 'ref' parameters instead of pointer-typed parameters for delegates. I'm not really sure what the advantage of using i.e. SDL_Event *
instead of ref SDL_Event
is, since you can use Unsafe
to map refs to/from pointers.
https://github.com/ppy/SDL3-CS/pull/147
This project creates a blittable bool type this way:
public readonly record struct SDLBool
{
private readonly byte value;
internal const byte FALSE_VALUE = 0;
internal const byte TRUE_VALUE = 1;
[Obsolete("Never explicitly construct an SDL bool.")]
public SDLBool()
{
}
internal SDLBool(byte value)
{
this.value = value;
}
public static implicit operator bool(SDLBool b) => b.value != FALSE_VALUE;
public static implicit operator SDLBool(bool b) => new SDLBool(b ? TRUE_VALUE : FALSE_VALUE);
public bool Equals(SDLBool other) => (bool)other == (bool)this;
public override int GetHashCode() => ((bool)this).GetHashCode();
private bool PrintMembers(StringBuilder builder)
{
builder.Append($"0x{value:x2}");
return true;
}
}
fyi: when runtime marshalling is enabled, bool types must be handled with a wrapper struct or by using the [MarshalAs(UnmanagedType.U1)]
attribute... that's because a bool
in C# can take up to 4 bytes.
However, when runtime marshalling is disabled you should be able to pass bool
as a 1 byte value, thus making it blittable. Not sure about returns though.
Note: that this will have some effects about blittable types. See here.
We have to support .NET Framework and disabling runtime marshaling is not an option there. I think at some point we'll look into also generating Core-specific bindings.
Apparently bool needs special care in C# and needs something like
[MarshalAs(UnmanagedType.U1)]
so that .NET Framework doesn't get mad about being a nonblittable type. SDL_Event in particular is affected by this; we need to cast toSDL.SDL_Event*
in a couple places and there's no real way around this.CC @kg