C#: use LayoutKind.Sequential for single-field exposed structs (IL2CPP wasm ABI) - #49
Open
Grantim wants to merge 2 commits into
Open
C#: use LayoutKind.Sequential for single-field exposed structs (IL2CPP wasm ABI)#49Grantim wants to merge 2 commits into
Grantim wants to merge 2 commits into
Conversation
Unity's IL2CPP compiles explicit-layout structs to a union with padding, and Clang's wasm32 ABI flattens only single-element structs, so a one-field exposed struct was returned through a hidden pointer and passed by pointer at the IL2CPP call site while the C side used a plain `int` (`wasm-ld: function signature mismatch`, traps or garbage at runtime). A sequential one-field struct compiles to a plain C struct with the same ABI as the C side, and for one field both layouts are identical anyway. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds `test_exposed_c()` taking and returning a single-field exposed struct by value, and regenerates the C and C# test outputs. In the C# outputs only the struct layout attributes of the single-field structs change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Unity WebGL (IL2CPP) builds of MeshLib's wasm bindings link with 622
wasm-ld: warning: function signature mismatch, one per C API function returning anMR::*Id; those calls trap at runtime. The ~1000 functions that take an Id by value get no warning (samei32on both sides) but silently receive a pointer to a stack copy instead of the value.Root cause: exposed structs are emitted with
LayoutKind.Explicit+FieldOffset. IL2CPP compiles explicit-layout structs to a union with padding (union { struct { ... }; uint8_t padding[N]; }), and Clang's wasm32 ABI only flattens single-element structs to scalars. So a one-field struct becomes an aggregate on the IL2CPP side (returned through a hidden pointer, passed by pointer) while the C side uses a plainint. IL2CPP compiles sequential structs to plain C structs (e.g.struct Int32_t { int32_t ___m_value; };), which Clang flattens exactly like the C side. Multi-field structs are passed indirectly on both sides and are unaffected.Fix
Exposed structs with exactly one non-static field are emitted with
LayoutKind.Sequentialand withoutFieldOffsetattributes. For one field both layouts are trivially identical (offset 0, size and alignment of the field), so nothing else changes: noDllImportsignatures, no C API. All other exposed structs keepLayoutKind.Explicit.Verification
llvm-22.1.8libs, like CI). The diff is confined to the attribute lines of the single-field structs (ConvCtorExposed,ExposedLayoutB,ExposedLayoutC,ConstNonconstConflicts,NameConflictsExposed::A,DeclOrder::*, and thestd::arraywrappers) plus the new test function.dotnet buildof the three generated C# test projects: 0 warnings.(i32 sret) -> voidand pass-by-pointer; the plain one-field struct gives() -> i32and pass-by-value, matching MeshLib's C API.test_exposed_c()covering a by-value parameter and return value of a single-field exposed struct.Supersedes #48, which fixed the same bug at the
DllImportlevel with more code.Follow-up in MeshLib: bump mrbind and regenerate the C# bindings; the Unity wasm link should then be free of
function signature mismatchwarnings.🤖 Generated with Claude Code