diff --git a/docs/generating_csharp.md b/docs/generating_csharp.md index 7a50918e..bac77a0f 100644 --- a/docs/generating_csharp.md +++ b/docs/generating_csharp.md @@ -182,6 +182,12 @@ Eventually we might add translation from the Doxygen comment annotations to thos This should be enough to at least display those comments in IDEs, but any `@...` doxygen tags will be left as is, instead of being translated into their proper XML form. +## Exposed structs at the P/Invoke boundary + +Structs exposed via `--expose-as-struct` (see [the C docs](/docs/generating_c.md#expose-simple-structs-as-structs)) are passed by value between C and C# as blittable C# structs, with one exception. If an exposed struct has exactly one field, and that field is a scalar (an arithmetic type other than `bool`, or an enum), then the `DllImport` declarations use that scalar directly, and the struct is wrapped and unwrapped on the C# side. The public C# API is unaffected, and the C side is unaffected too, because in C both spellings have the same ABI. + +This is needed for Unity's IL2CPP on WebAssembly. IL2CPP wraps every C# struct into a union with padding, and on wasm32 Clang only passes and returns single-element structs as plain scalars, which that wrapper no longer is. So the IL2CPP-compiled call site would return such a struct through a hidden pointer and pass it by pointer, while the C library returns and accepts a plain scalar (`wasm-ld` reports this as `function signature mismatch`, and the calls trap or read garbage at runtime). A scalar has the same ABI everywhere. Structs with more than one field don't have this problem, since both sides agree on passing those indirectly. + ## Distributing the C# bindings as a Nuget package This is not a full explanation, but a rought outline of what you need to do. diff --git a/src/generators/csharp/generator.cpp b/src/generators/csharp/generator.cpp index b4de8111..865e8ca2 100644 --- a/src/generators/csharp/generator.cpp +++ b/src/generators/csharp/generator.cpp @@ -933,6 +933,56 @@ namespace mrbind::CSharp return CppToCSharpIdentifier(name.parts.back()); } + std::optional Generator::GetExposedStructSingleScalarField(const CInterop::TypeKinds::Class &class_desc, const cppdecl::QualifiedName &cpp_class_name) + { + assert(class_desc.kind == CInterop::ClassKind::exposed_struct); + + // Find the only non-static field, if any. + const CInterop::ClassField *field = nullptr; + for (const CInterop::ClassField &elem : class_desc.fields) + { + if (elem.is_static) + continue; + if (field) + return {}; // More than one field. + field = &elem; + } + if (!field) + return {}; + + cppdecl::Type cpp_type = ParseTypeOrThrow(field->type); + if (!cpp_type.modifiers.empty()) + return {}; // Arrays and pointers. + cpp_type.RemoveQualifiers(cppdecl::CvQualifiers::const_); + const std::string cpp_type_str = CppdeclToCode(cpp_type); + + std::string csharp_type; + if (auto prim = c_desc.platform_info.FindPrimitiveType(cpp_type_str)) + { + // Not `bool`, because the C# struct stores it as a `byte` behind a property, and because `bool` isn't blittable when passed by value anyway. + if (prim->kind == PrimitiveTypeInfo::Kind::boolean) + return {}; + + auto csharp_type_opt = CToCSharpPrimitiveTypeOpt(cpp_type_str, false); + if (!csharp_type_opt) + return {}; + csharp_type = std::string(*csharp_type_opt); + } + else if (auto type_desc = c_desc.FindTypeOpt(cpp_type_str); type_desc && std::holds_alternative(type_desc->var)) + { + csharp_type = CppToCSharpEnumName(cpp_type.simple_type.name); + } + else + { + return {}; // Nested exposed structs and anything else. + } + + return ExposedStructSingleScalarField{ + .csharp_type = std::move(csharp_type), + .csharp_field_name = CppToCSharpFieldName(cpp_class_name, false, field->full_name), + }; + } + std::string Generator::CppToCSharpByValueHelperName(cppdecl::QualifiedName name, bool is_shared) { // Must make this before adjusting the name. @@ -1704,15 +1754,40 @@ namespace mrbind::CSharp const std::string csharp_value_type = CppToCSharpExposedStructName(cpp_effective_type.simple_type.name); const std::string csharp_in_opt_type = CppToCSharpInOptStructHelperName(cpp_effective_type.simple_type.name); + // Exposed structs with exactly one scalar field are passed through `DllImport` by value as that scalar, not as the struct. + // In C both spellings have the same ABI on every platform we care about, so the C side is unaffected. + // This is needed for Unity's IL2CPP on wasm32. IL2CPP wraps every C# struct into a union with padding, and Clang only + // passes/returns single-element structs as plain scalars on wasm32, which that wrapper isn't. So the IL2CPP-compiled + // call site returns such a struct through a hidden pointer and passes it by pointer, while the C library returns and + // accepts a plain scalar (`wasm-ld` warns about `function signature mismatch`, and the calls trap or read garbage). + // A scalar has the same ABI on both sides. Structs with several fields are fine, both sides pass those indirectly. + // The pass-by-pointer variant below (for default arguments) is unaffected, pointers are always the same. + const std::optional scalar_field = GetExposedStructSingleScalarField(elem, cpp_effective_type.simple_type.name); + const std::string csharp_dllimport_type = scalar_field ? scalar_field->csharp_type : csharp_value_type; + + TypeBinding::ReturnUsage return_usage{ + .cpp_never_throws = true, // Exposed structs must be trivial, which means all their non-deleted SMFs must be trivial too, which implies non-throwing. + .dllimport_return_type = csharp_dllimport_type, + .csharp_return_type = csharp_value_type, + // Default `make_return_statements` is good enough when not unwrapping the scalar. + }; + if (scalar_field) + { + return_usage.make_return_statements = [csharp_value_type, csharp_field_name = scalar_field->csharp_field_name](const std::string &target, const std::string &expr) + { + return target + " new " + csharp_value_type + " {" + csharp_field_name + " = " + expr + "};"; + }; + } + return CreateBinding({ .param_usage = TypeBinding::ParamUsage{ - .make_strings = [csharp_value_type](const std::string &name, bool /*have_useless_defarg*/) + .make_strings = [csharp_value_type, csharp_dllimport_type, scalar_field](const std::string &name, bool /*have_useless_defarg*/) { return TypeBinding::ParamUsage::Strings{ .cpp_never_throws = true, // Exposed structs must be trivial, which means all their non-deleted SMFs must be trivial too, which implies non-throwing. - .dllimport_decl_params = {{.type = csharp_value_type, .name = name}}, + .dllimport_decl_params = {{.type = csharp_dllimport_type, .name = name}}, .csharp_decl_params = {{.type = csharp_value_type, .name = name}}, - .dllimport_args = {name}, + .dllimport_args = {scalar_field ? name + "." + scalar_field->csharp_field_name : name}, }; }, }, @@ -1727,12 +1802,7 @@ namespace mrbind::CSharp }; }, }, - .return_usage = TypeBinding::ReturnUsage{ - .cpp_never_throws = true, // Exposed structs must be trivial, which means all their non-deleted SMFs must be trivial too, which implies non-throwing. - .dllimport_return_type = csharp_value_type, - .csharp_return_type = csharp_value_type, - // Default `make_return_expr` is good enough! - }, + .return_usage = std::move(return_usage), }); } break; @@ -4807,7 +4877,8 @@ namespace mrbind::CSharp { // You can assign to `this`, and it assigns elementwise! Nice. // See: https://stackoverflow.com/q/10038598/2752075 - file.WriteString("this = " + expr + ";\n"); + // This goes through the return binding because exposed structs with a single scalar field are returned from C as that scalar, see `GetTypeBindingOpt()`. + file.WriteString(ret_binding->MakeReturnStatements("this =", expr) + "\n"); } else { @@ -4821,7 +4892,8 @@ namespace mrbind::CSharp ctor_expr = "(_Underlying *)" + generator.RequestHelper("_Alloc") + "(" + class_size_str + ")"; - post_ctor_statements = "*(" + generator.CppToCSharpExposedStructName(generator.ParseNameOrThrow(func_like.ret.cpp_type)) + " *)_UnderlyingPtr = " + expr + ";\n"; + // This goes through the return binding because exposed structs with a single scalar field are returned from C as that scalar, see `GetTypeBindingOpt()`. + post_ctor_statements = ret_binding->MakeReturnStatements("*(" + generator.CppToCSharpExposedStructName(generator.ParseNameOrThrow(func_like.ret.cpp_type)) + " *)_UnderlyingPtr =", expr) + "\n"; } else { diff --git a/src/generators/csharp/generator.h b/src/generators/csharp/generator.h index 0400c53d..6c36aecb 100644 --- a/src/generators/csharp/generator.h +++ b/src/generators/csharp/generator.h @@ -670,6 +670,19 @@ namespace mrbind::CSharp // since the result can be affected by the properties of the class. [[nodiscard]] std::string CppToCSharpUnqualExposedStructName(cppdecl::QualifiedName name); + // Describes the only field of an exposed struct that has exactly one scalar field. See `GetExposedStructSingleScalarField()`. + struct ExposedStructSingleScalarField + { + // The C# type of the field, e.g. `int`. + std::string csharp_type; + // The C# name of the field in the exposed struct. + std::string csharp_field_name; + }; + // If the exposed struct `class_desc` (named `cpp_class_name` in C++) has exactly one non-static field, and that field is either an arithmetic type + // other than `bool` or an enum, returns the description of that field. Otherwise returns null. + // Such structs are passed through `DllImport` by value as that field rather than as the struct itself. See `GetTypeBindingOpt()` for the explanation. + [[nodiscard]] std::optional GetExposedStructSingleScalarField(const CInterop::TypeKinds::Class &class_desc, const cppdecl::QualifiedName &cpp_class_name); + // Converts a C++ qualified class name to a C# name of its helper that's used to pass it by value. // This only makes sense for classes that use the pass-by enum. [[nodiscard]] std::string CppToCSharpByValueHelperName(cppdecl::QualifiedName name, bool is_shared); diff --git a/test/input/MR/test_csharp.h b/test/input/MR/test_csharp.h index f2eef0cf..ebed9791 100644 --- a/test/input/MR/test_csharp.h +++ b/test/input/MR/test_csharp.h @@ -1065,6 +1065,9 @@ namespace MR::CSharp int x; }; + // Single-field exposed structs are passed through P/Invoke as their only field. This tests by-value parameters and return values. + inline ExposedLayoutC test_exposed_c(ExposedLayoutC a, ExposedLayoutC b = {}) {a.x += b.x; return a;} + // Test various array members. struct ArrayMembers diff --git a/test/output_c/include/MR/test_csharp.h b/test/output_c/include/MR/test_csharp.h index 40486b2a..ebf7f289 100644 --- a/test/output_c/include/MR/test_csharp.h +++ b/test/output_c/include/MR/test_csharp.h @@ -6312,6 +6312,11 @@ MR_C_API MR_CSharp_ExposedLayoutB MR_CSharp_ExposedLayoutB_Construct_1(const MR_ /// Parameter `_2` can not be null. It is a single object. MR_C_API bool MR_C_equal_MR_CSharp_ExposedLayoutB(const MR_CSharp_ExposedLayoutB *_1, const MR_CSharp_ExposedLayoutB *_2); +// Single-field exposed structs are passed through P/Invoke as their only field. This tests by-value parameters and return values. +/// Generated from function `MR::CSharp::test_exposed_c`. +/// Parameter `b` has a default argument: `{}`, pass a null pointer to use it. +MR_C_API MR_CSharp_ExposedLayoutC MR_CSharp_test_exposed_c(MR_CSharp_ExposedLayoutC a, const MR_CSharp_ExposedLayoutC *b); + /// Returns a pointer to a member variable of class `MR::CSharp::ArrayMembers` named `i`. /// Parameter `_this` can not be null. It is a single object. /// The returned pointer will never be null. It is non-owning, do NOT destroy it. diff --git a/test/output_c/source/MR/test_csharp.cpp b/test/output_c/source/MR/test_csharp.cpp index 65968fc7..6c0a21e0 100644 --- a/test/output_c/source/MR/test_csharp.cpp +++ b/test/output_c/source/MR/test_csharp.cpp @@ -9550,6 +9550,18 @@ bool MR_C_equal_MR_CSharp_ExposedLayoutB(const MR_CSharp_ExposedLayoutB *_1, con ) // MRBINDC_TRY } +MR_CSharp_ExposedLayoutC MR_CSharp_test_exposed_c(MR_CSharp_ExposedLayoutC a, const MR_CSharp_ExposedLayoutC *b) +{ + MRBINDC_TRY( + using namespace MR; + using namespace CSharp; + return MRBINDC_BIT_CAST((MR_CSharp_ExposedLayoutC), ::MR::CSharp::test_exposed_c( + MRBINDC_BIT_CAST((MR::CSharp::ExposedLayoutC), a), + (b ? MRBINDC_BIT_CAST((MR::CSharp::ExposedLayoutC), *b) : MR::CSharp::ExposedLayoutC(MR::CSharp::ExposedLayoutC{})) + )); + ) // MRBINDC_TRY +} + const int *MR_CSharp_ArrayMembers_Get_i(const MR_CSharp_ArrayMembers *_this) { return std::addressof(((_this ? void() : MRBINDC_THROW("Parameter `_this` can not be null.", void)), *(const MR::CSharp::ArrayMembers *)(_this)).i); diff --git a/test/output_c_fixed_typedefs/include/MR/test_csharp.h b/test/output_c_fixed_typedefs/include/MR/test_csharp.h index 4fd33589..3f58c286 100644 --- a/test/output_c_fixed_typedefs/include/MR/test_csharp.h +++ b/test/output_c_fixed_typedefs/include/MR/test_csharp.h @@ -6128,6 +6128,11 @@ MR_C_API MR_CSharp_ExposedLayoutB MR_CSharp_ExposedLayoutB_Construct_1(const MR_ // Parameter `_2` can not be null. It is a single object. MR_C_API bool MR_C_equal_MR_CSharp_ExposedLayoutB(const MR_CSharp_ExposedLayoutB *_1, const MR_CSharp_ExposedLayoutB *_2); +// Single-field exposed structs are passed through P/Invoke as their only field. This tests by-value parameters and return values. +// Generated from function `MR::CSharp::test_exposed_c`. +// Parameter `b` has a default argument: `{}`, pass a null pointer to use it. +MR_C_API MR_CSharp_ExposedLayoutC MR_CSharp_test_exposed_c(MR_CSharp_ExposedLayoutC a, const MR_CSharp_ExposedLayoutC *b); + // Returns a pointer to a member variable of class `MR::CSharp::ArrayMembers` named `i`. // Parameter `_this` can not be null. It is a single object. // The returned pointer will never be null. It is non-owning, do NOT destroy it. diff --git a/test/output_c_fixed_typedefs/source/MR/test_csharp.cpp b/test/output_c_fixed_typedefs/source/MR/test_csharp.cpp index 9f0434a2..df275891 100644 --- a/test/output_c_fixed_typedefs/source/MR/test_csharp.cpp +++ b/test/output_c_fixed_typedefs/source/MR/test_csharp.cpp @@ -6882,6 +6882,14 @@ bool MR_C_equal_MR_CSharp_ExposedLayoutB(const MR_CSharp_ExposedLayoutB *_1, con ); } +MR_CSharp_ExposedLayoutC MR_CSharp_test_exposed_c(MR_CSharp_ExposedLayoutC a, const MR_CSharp_ExposedLayoutC *b) +{ + return MRBINDC_BIT_CAST((MR_CSharp_ExposedLayoutC), ::MR::CSharp::test_exposed_c( + MRBINDC_BIT_CAST((MR::CSharp::ExposedLayoutC), a), + (b ? MRBINDC_BIT_CAST((MR::CSharp::ExposedLayoutC), *b) : MR::CSharp::ExposedLayoutC(MR::CSharp::ExposedLayoutC{})) + )); +} + const int32_t *MR_CSharp_ArrayMembers_Get_i(const MR_CSharp_ArrayMembers *_this) { return std::addressof(((_this ? void() : MRBINDC_THROW("Parameter `_this` can not be null.", void)), *(const MR::CSharp::ArrayMembers *)(_this)).i); diff --git a/test/output_c_fixed_typedefs_64_only/include/MR/test_csharp.h b/test/output_c_fixed_typedefs_64_only/include/MR/test_csharp.h index 691e4495..dd0f43b8 100644 --- a/test/output_c_fixed_typedefs_64_only/include/MR/test_csharp.h +++ b/test/output_c_fixed_typedefs_64_only/include/MR/test_csharp.h @@ -6311,6 +6311,11 @@ MR_C_API MR_CSharp_ExposedLayoutB MR_CSharp_ExposedLayoutB_Construct_1(const MR_ /// Parameter `_2` can not be null. It is a single object. MR_C_API bool MR_C_equal_MR_CSharp_ExposedLayoutB(const MR_CSharp_ExposedLayoutB *_1, const MR_CSharp_ExposedLayoutB *_2); +// Single-field exposed structs are passed through P/Invoke as their only field. This tests by-value parameters and return values. +/// Generated from function `MR::CSharp::test_exposed_c`. +/// Parameter `b` has a default argument: `{}`, pass a null pointer to use it. +MR_C_API MR_CSharp_ExposedLayoutC MR_CSharp_test_exposed_c(MR_CSharp_ExposedLayoutC a, const MR_CSharp_ExposedLayoutC *b); + /// Returns a pointer to a member variable of class `MR::CSharp::ArrayMembers` named `i`. /// Parameter `_this` can not be null. It is a single object. /// The returned pointer will never be null. It is non-owning, do NOT destroy it. diff --git a/test/output_c_fixed_typedefs_64_only/source/MR/test_csharp.cpp b/test/output_c_fixed_typedefs_64_only/source/MR/test_csharp.cpp index c6ba68ac..ea50349e 100644 --- a/test/output_c_fixed_typedefs_64_only/source/MR/test_csharp.cpp +++ b/test/output_c_fixed_typedefs_64_only/source/MR/test_csharp.cpp @@ -7138,6 +7138,14 @@ bool MR_C_equal_MR_CSharp_ExposedLayoutB(const MR_CSharp_ExposedLayoutB *_1, con ); } +MR_CSharp_ExposedLayoutC MR_CSharp_test_exposed_c(MR_CSharp_ExposedLayoutC a, const MR_CSharp_ExposedLayoutC *b) +{ + return MRBINDC_BIT_CAST((MR_CSharp_ExposedLayoutC), ::MR::CSharp::test_exposed_c( + MRBINDC_BIT_CAST((MR::CSharp::ExposedLayoutC), a), + (b ? MRBINDC_BIT_CAST((MR::CSharp::ExposedLayoutC), *b) : MR::CSharp::ExposedLayoutC(MR::CSharp::ExposedLayoutC{})) + )); +} + const int *MR_CSharp_ArrayMembers_Get_i(const MR_CSharp_ArrayMembers *_this) { return std::addressof(((_this ? void() : MRBINDC_THROW("Parameter `_this` can not be null.", void)), *(const MR::CSharp::ArrayMembers *)(_this)).i); diff --git a/test/output_csharp/src/MR/test_csharp.cs b/test/output_csharp/src/MR/test_csharp.cs index e810ba01..8de9690d 100644 --- a/test/output_csharp/src/MR/test_csharp.cs +++ b/test/output_csharp/src/MR/test_csharp.cs @@ -13643,10 +13643,10 @@ public unsafe ConstBox_ConvCtorExposed(ConstBox_ConvCtorExposed _other) : this(n public unsafe ConstBox_ConvCtorExposed(int _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); MR.CS.Misc._Exceptions.Prepare(); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = __MR_CSharp_ConvCtorExposed_Construct(_1); + *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -13683,10 +13683,10 @@ public unsafe Box_ConvCtorExposed(ConstBox_ConvCtorExposed _other) : this(null, public unsafe Box_ConvCtorExposed(int _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); MR.CS.Misc._Exceptions.Prepare(); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = __MR_CSharp_ConvCtorExposed_Construct(_1); + *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -13713,9 +13713,9 @@ public struct ConvCtorExposed public unsafe ConvCtorExposed(int _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); MR.CS.Misc._Exceptions.Prepare(); - this = __MR_CSharp_ConvCtorExposed_Construct(_1); + this = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -15720,10 +15720,10 @@ public unsafe ConstBox_ExposedLayoutB(ConstBox_ExposedLayoutB _other) : this(nul public unsafe ConstBox_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); MR.CS.Misc._Exceptions.Prepare(); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -15732,10 +15732,10 @@ public unsafe ConstBox_ExposedLayoutB(int _1, int _2) : this(null, is_owning: tr public unsafe ConstBox_ExposedLayoutB(MR.CS.CSharp.Const_A _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); MR.CS.Misc._Exceptions.Prepare(); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; _KeepAlive(_1); MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -15809,10 +15809,10 @@ public unsafe Box_ExposedLayoutB(ConstBox_ExposedLayoutB _other) : this(null, is public unsafe Box_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); MR.CS.Misc._Exceptions.Prepare(); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -15821,10 +15821,10 @@ public unsafe Box_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) public unsafe Box_ExposedLayoutB(MR.CS.CSharp.Const_A _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); MR.CS.Misc._Exceptions.Prepare(); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; _KeepAlive(_1); MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -15853,9 +15853,9 @@ public struct ExposedLayoutB : System.IEquatable public unsafe ExposedLayoutB(int _1, int _2) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); MR.CS.Misc._Exceptions.Prepare(); - this = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + this = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -15864,9 +15864,9 @@ public unsafe ExposedLayoutB(int _1, int _2) public unsafe ExposedLayoutB(MR.CS.CSharp.Const_A _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); MR.CS.Misc._Exceptions.Prepare(); - this = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + this = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; MR.CS.Misc._Exceptions.ThrowIfNeeded(); } @@ -25651,6 +25651,19 @@ public static unsafe ref readonly MR.CS.CSharp.ExposedLayoutSh TestExposedCref(i if (__c_ret is not null) return *__c_ret; else return null; } + // Single-field exposed structs are passed through P/Invoke as their only field. This tests by-value parameters and return values. + /// Generated from function `MR::CSharp::test_exposed_c`. + /// Parameter `b` defaults to `{}`. + public static unsafe MR.CS.CSharp.ExposedLayoutC TestExposedC(MR.CS.CSharp.ExposedLayoutC a, MR.CS.CSharp._InOpt_ExposedLayoutC b = default) + { + [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_test_exposed_c", ExactSpelling = true)] + extern static int __MR_CSharp_test_exposed_c(int a, MR.CS.CSharp.ExposedLayoutC *b); + MR.CS.Misc._Exceptions.Prepare(); + var __c_ret = __MR_CSharp_test_exposed_c(a.x, b.HasValue ? &b.Object : null); + MR.CS.Misc._Exceptions.ThrowIfNeeded(); + return new MR.CS.CSharp.ExposedLayoutC {x = __c_ret}; + } + /// Generated from function `MR::CSharp::test_optint`. /// Parameter `b` defaults to `default_optint`. /// Parameter `c` defaults to `default_optint`. diff --git a/test/output_csharp/src/MR/test_declaration_order.cs b/test/output_csharp/src/MR/test_declaration_order.cs index 302cbef8..a798fdd2 100644 --- a/test/output_csharp/src/MR/test_declaration_order.cs +++ b/test/output_csharp/src/MR/test_declaration_order.cs @@ -86,11 +86,11 @@ public unsafe Box_A(ConstBox_A _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.A.B C() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_c", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A.B __MR_DeclOrder_A_c(_Underlying *_this); + extern static int __MR_DeclOrder_A_c(_Underlying *_this); MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_A_c(_UnderlyingPtr); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.A.B {bleh = __c_ret}; } /// Generated from method `MR::DeclOrder::A::d`. @@ -124,13 +124,13 @@ public struct A public unsafe MR.CS.DeclOrder.A.B C() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_c", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A.B __MR_DeclOrder_A_c(MR.CS.DeclOrder.A *_this); + extern static int __MR_DeclOrder_A_c(MR.CS.DeclOrder.A *_this); fixed (MR.CS.DeclOrder.A *__ptr__this = &this) { MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_A_c(__ptr__this); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.A.B {bleh = __c_ret}; } } @@ -228,11 +228,11 @@ public unsafe Box_B(ConstBox_B _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.A A() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_B_a", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A __MR_DeclOrder_A_B_a(_Underlying *_this); + extern static int __MR_DeclOrder_A_B_a(_Underlying *_this); MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_A_B_a(_UnderlyingPtr); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.A {blah = __c_ret}; } /// Generated from method `MR::DeclOrder::A::B::b`. @@ -265,13 +265,13 @@ public struct B public unsafe MR.CS.DeclOrder.A A() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_B_a", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A __MR_DeclOrder_A_B_a(MR.CS.DeclOrder.A.B *_this); + extern static int __MR_DeclOrder_A_B_a(MR.CS.DeclOrder.A.B *_this); fixed (MR.CS.DeclOrder.A.B *__ptr__this = &this) { MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_A_B_a(__ptr__this); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.A {blah = __c_ret}; } } @@ -513,11 +513,11 @@ public unsafe Box_C_False(ConstBox_C_False _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.C_True Blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_false_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_True __MR_DeclOrder_C_false_blah(_Underlying *_this); + extern static int __MR_DeclOrder_C_false_blah(_Underlying *_this); MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_C_false_blah(_UnderlyingPtr); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.C_True {bleh = __c_ret}; } } @@ -539,13 +539,13 @@ public struct C_False public unsafe MR.CS.DeclOrder.C_True Blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_false_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_True __MR_DeclOrder_C_false_blah(MR.CS.DeclOrder.C_False *_this); + extern static int __MR_DeclOrder_C_false_blah(MR.CS.DeclOrder.C_False *_this); fixed (MR.CS.DeclOrder.C_False *__ptr__this = &this) { MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_C_false_blah(__ptr__this); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.C_True {bleh = __c_ret}; } } } @@ -699,11 +699,11 @@ public unsafe Box_C_True(ConstBox_C_True _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.C_False Blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_true_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_False __MR_DeclOrder_C_true_blah(_Underlying *_this); + extern static int __MR_DeclOrder_C_true_blah(_Underlying *_this); MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_C_true_blah(_UnderlyingPtr); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.C_False {bleh = __c_ret}; } } @@ -725,13 +725,13 @@ public struct C_True public unsafe MR.CS.DeclOrder.C_False Blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_true_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_False __MR_DeclOrder_C_true_blah(MR.CS.DeclOrder.C_True *_this); + extern static int __MR_DeclOrder_C_true_blah(MR.CS.DeclOrder.C_True *_this); fixed (MR.CS.DeclOrder.C_True *__ptr__this = &this) { MR.CS.Misc._Exceptions.Prepare(); var __c_ret = __MR_DeclOrder_C_true_blah(__ptr__this); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.DeclOrder.C_False {bleh = __c_ret}; } } } diff --git a/test/output_csharp/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs b/test/output_csharp/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs index cf6489c4..b993fce0 100644 --- a/test/output_csharp/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs +++ b/test/output_csharp/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs @@ -68,27 +68,27 @@ public static unsafe implicit operator bool(MR.CS.Std.Const_Function_MRCSharpExp public unsafe MR.CS.CSharp.ExposedLayoutC Call(MR.CS.CSharp.ExposedLayoutC _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutC __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_Underlying *_this, MR.CS.CSharp.ExposedLayoutC _1); + extern static int __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_Underlying *_this, int _1); MR.CS.Misc._Exceptions.Prepare(); - var __c_ret = __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_UnderlyingPtr, _1); + var __c_ret = __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_UnderlyingPtr, _1.x); MR.CS.Misc._Exceptions.ThrowIfNeeded(); - return __c_ret; + return new MR.CS.CSharp.ExposedLayoutC {x = __c_ret}; } // Custom extras: public delegate MR.CS.CSharp.ExposedLayoutC Delegate(ref readonly MR.CS.CSharp.ExposedLayoutC _1); - private protected unsafe delegate MR.CS.CSharp.ExposedLayoutC _CDelegate(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value); + private protected unsafe delegate int _CDelegate(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value); - private protected static unsafe MR.CS.CSharp.ExposedLayoutC _CCallWrapper(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value) + private protected static unsafe int _CCallWrapper(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value) { try { ref readonly MR.CS.CSharp.ExposedLayoutC _arg_1 = ref *(MR.CS.CSharp.ExposedLayoutC *)sizeof(MR.CS.CSharp.ExposedLayoutC); // Uninitialized ref. _arg_1 = ref *_1; MR.CS.CSharp.ExposedLayoutC _ret = ((Delegate)System.Runtime.InteropServices.GCHandle.FromIntPtr((nint)_userdata).Target!)(in _arg_1); - return _ret; + return _ret.x; } catch (Exception __e) { diff --git a/test/output_csharp_fixed_typedefs/src/MR/test_csharp.cs b/test/output_csharp_fixed_typedefs/src/MR/test_csharp.cs index 479f7aad..d798f78a 100644 --- a/test/output_csharp_fixed_typedefs/src/MR/test_csharp.cs +++ b/test/output_csharp_fixed_typedefs/src/MR/test_csharp.cs @@ -14066,9 +14066,9 @@ public unsafe ConstBox_ConvCtorExposed(ConstBox_ConvCtorExposed _other) : this(n public unsafe ConstBox_ConvCtorExposed(int _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = __MR_CSharp_ConvCtorExposed_Construct(_1); + *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; } /// @@ -14118,9 +14118,9 @@ public unsafe Box_ConvCtorExposed(ConstBox_ConvCtorExposed _other) : this(null, public unsafe Box_ConvCtorExposed(int _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = __MR_CSharp_ConvCtorExposed_Construct(_1); + *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; } /// @@ -14156,8 +14156,8 @@ public struct ConvCtorExposed public unsafe ConvCtorExposed(int _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); - this = __MR_CSharp_ConvCtorExposed_Construct(_1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); + this = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; } /// @@ -16286,9 +16286,9 @@ public unsafe ConstBox_ExposedLayoutB(ConstBox_ExposedLayoutB _other) : this(nul public unsafe ConstBox_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -16298,9 +16298,9 @@ public unsafe ConstBox_ExposedLayoutB(int _1, int _2) : this(null, is_owning: tr public unsafe ConstBox_ExposedLayoutB(MR.CS.CSharp.Const_A _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -16385,9 +16385,9 @@ public unsafe Box_ExposedLayoutB(ConstBox_ExposedLayoutB _other) : this(null, is public unsafe Box_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -16397,9 +16397,9 @@ public unsafe Box_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) public unsafe Box_ExposedLayoutB(MR.CS.CSharp.Const_A _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -16436,8 +16436,8 @@ public struct ExposedLayoutB : System.IEquatable public unsafe ExposedLayoutB(int _1, int _2) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); - this = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + this = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -16447,8 +16447,8 @@ public unsafe ExposedLayoutB(int _1, int _2) public unsafe ExposedLayoutB(MR.CS.CSharp.Const_A _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); - this = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + this = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -27133,6 +27133,18 @@ public static unsafe ref readonly MR.CS.CSharp.ExposedLayoutSh testExposedCref(i if (__c_ret is not null) return *__c_ret; else return null; } + // Single-field exposed structs are passed through P/Invoke as their only field. This tests by-value parameters and return values. + /// + /// Generated from function `MR::CSharp::test_exposed_c`. + /// Parameter `b` defaults to `{}`. + /// + public static unsafe MR.CS.CSharp.ExposedLayoutC testExposedC(MR.CS.CSharp.ExposedLayoutC a, MR.CS.CSharp._InOpt_ExposedLayoutC b = default) + { + [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_test_exposed_c", ExactSpelling = true)] + extern static int __MR_CSharp_test_exposed_c(int a, MR.CS.CSharp.ExposedLayoutC *b); + return new MR.CS.CSharp.ExposedLayoutC {x = __MR_CSharp_test_exposed_c(a.x, b.HasValue ? &b.Object : null)}; + } + /// /// Generated from function `MR::CSharp::test_optint`. /// Parameter `b` defaults to `MR::CSharp::default_optint`. diff --git a/test/output_csharp_fixed_typedefs/src/MR/test_declaration_order.cs b/test/output_csharp_fixed_typedefs/src/MR/test_declaration_order.cs index 99302f26..92a9b9a4 100644 --- a/test/output_csharp_fixed_typedefs/src/MR/test_declaration_order.cs +++ b/test/output_csharp_fixed_typedefs/src/MR/test_declaration_order.cs @@ -112,8 +112,8 @@ public unsafe Box_A(ConstBox_A _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.A.B c() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_c", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A.B __MR_DeclOrder_A_c(_Underlying *_this); - return __MR_DeclOrder_A_c(_UnderlyingPtr); + extern static int __MR_DeclOrder_A_c(_Underlying *_this); + return new MR.CS.DeclOrder.A.B {bleh = __MR_DeclOrder_A_c(_UnderlyingPtr)}; } /// @@ -154,10 +154,10 @@ public struct A public unsafe MR.CS.DeclOrder.A.B c() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_c", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A.B __MR_DeclOrder_A_c(MR.CS.DeclOrder.A *_this); + extern static int __MR_DeclOrder_A_c(MR.CS.DeclOrder.A *_this); fixed (MR.CS.DeclOrder.A *__ptr__this = &this) { - return __MR_DeclOrder_A_c(__ptr__this); + return new MR.CS.DeclOrder.A.B {bleh = __MR_DeclOrder_A_c(__ptr__this)}; } } @@ -280,8 +280,8 @@ public unsafe Box_B(ConstBox_B _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.A a() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_B_a", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A __MR_DeclOrder_A_B_a(_Underlying *_this); - return __MR_DeclOrder_A_B_a(_UnderlyingPtr); + extern static int __MR_DeclOrder_A_B_a(_Underlying *_this); + return new MR.CS.DeclOrder.A {blah = __MR_DeclOrder_A_B_a(_UnderlyingPtr)}; } /// @@ -321,10 +321,10 @@ public struct B public unsafe MR.CS.DeclOrder.A a() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_B_a", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A __MR_DeclOrder_A_B_a(MR.CS.DeclOrder.A.B *_this); + extern static int __MR_DeclOrder_A_B_a(MR.CS.DeclOrder.A.B *_this); fixed (MR.CS.DeclOrder.A.B *__ptr__this = &this) { - return __MR_DeclOrder_A_B_a(__ptr__this); + return new MR.CS.DeclOrder.A {blah = __MR_DeclOrder_A_B_a(__ptr__this)}; } } @@ -603,8 +603,8 @@ public unsafe Box_C_False(ConstBox_C_False _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.C_True blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_false_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_True __MR_DeclOrder_C_false_blah(_Underlying *_this); - return __MR_DeclOrder_C_false_blah(_UnderlyingPtr); + extern static int __MR_DeclOrder_C_false_blah(_Underlying *_this); + return new MR.CS.DeclOrder.C_True {bleh = __MR_DeclOrder_C_false_blah(_UnderlyingPtr)}; } } @@ -634,10 +634,10 @@ public struct C_False public unsafe MR.CS.DeclOrder.C_True blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_false_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_True __MR_DeclOrder_C_false_blah(MR.CS.DeclOrder.C_False *_this); + extern static int __MR_DeclOrder_C_false_blah(MR.CS.DeclOrder.C_False *_this); fixed (MR.CS.DeclOrder.C_False *__ptr__this = &this) { - return __MR_DeclOrder_C_false_blah(__ptr__this); + return new MR.CS.DeclOrder.C_True {bleh = __MR_DeclOrder_C_false_blah(__ptr__this)}; } } } @@ -823,8 +823,8 @@ public unsafe Box_C_True(ConstBox_C_True _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.C_False blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_true_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_False __MR_DeclOrder_C_true_blah(_Underlying *_this); - return __MR_DeclOrder_C_true_blah(_UnderlyingPtr); + extern static int __MR_DeclOrder_C_true_blah(_Underlying *_this); + return new MR.CS.DeclOrder.C_False {bleh = __MR_DeclOrder_C_true_blah(_UnderlyingPtr)}; } } @@ -854,10 +854,10 @@ public struct C_True public unsafe MR.CS.DeclOrder.C_False blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_true_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_False __MR_DeclOrder_C_true_blah(MR.CS.DeclOrder.C_True *_this); + extern static int __MR_DeclOrder_C_true_blah(MR.CS.DeclOrder.C_True *_this); fixed (MR.CS.DeclOrder.C_True *__ptr__this = &this) { - return __MR_DeclOrder_C_true_blah(__ptr__this); + return new MR.CS.DeclOrder.C_False {bleh = __MR_DeclOrder_C_true_blah(__ptr__this)}; } } } diff --git a/test/output_csharp_fixed_typedefs/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs b/test/output_csharp_fixed_typedefs/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs index dc86ac14..4018f136 100644 --- a/test/output_csharp_fixed_typedefs/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs +++ b/test/output_csharp_fixed_typedefs/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs @@ -75,22 +75,22 @@ public static unsafe implicit operator bool(MR.CS.Std.Const_Function_MRCSharpExp public unsafe MR.CS.CSharp.ExposedLayoutC call(MR.CS.CSharp.ExposedLayoutC _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutC __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_Underlying *_this, MR.CS.CSharp.ExposedLayoutC _1); - return __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_UnderlyingPtr, _1); + extern static int __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_Underlying *_this, int _1); + return new MR.CS.CSharp.ExposedLayoutC {x = __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_UnderlyingPtr, _1.x)}; } // Custom extras: public delegate MR.CS.CSharp.ExposedLayoutC Delegate(ref readonly MR.CS.CSharp.ExposedLayoutC _1); - private protected unsafe delegate MR.CS.CSharp.ExposedLayoutC _CDelegate(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value); + private protected unsafe delegate int _CDelegate(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value); - private protected static unsafe MR.CS.CSharp.ExposedLayoutC _CCallWrapper(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value) + private protected static unsafe int _CCallWrapper(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value) { ref readonly MR.CS.CSharp.ExposedLayoutC _arg_1 = ref *(MR.CS.CSharp.ExposedLayoutC *)sizeof(MR.CS.CSharp.ExposedLayoutC); // Uninitialized ref. _arg_1 = ref *_1; MR.CS.CSharp.ExposedLayoutC _ret = ((Delegate)System.Runtime.InteropServices.GCHandle.FromIntPtr((nint)_userdata).Target!)(in _arg_1); - return _ret; + return _ret.x; } /// diff --git a/test/output_csharp_fixed_typedefs_64_only/src/MR/test_csharp.cs b/test/output_csharp_fixed_typedefs_64_only/src/MR/test_csharp.cs index 8175b4d6..8d35f1a3 100644 --- a/test/output_csharp_fixed_typedefs_64_only/src/MR/test_csharp.cs +++ b/test/output_csharp_fixed_typedefs_64_only/src/MR/test_csharp.cs @@ -15214,9 +15214,9 @@ public unsafe ConstBox_ConvCtorExposed(ConstBox_ConvCtorExposed _other) : this(n public unsafe ConstBox_ConvCtorExposed(int _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = __MR_CSharp_ConvCtorExposed_Construct(_1); + *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; } /// @@ -15266,9 +15266,9 @@ public unsafe Box_ConvCtorExposed(ConstBox_ConvCtorExposed _other) : this(null, public unsafe Box_ConvCtorExposed(int _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = __MR_CSharp_ConvCtorExposed_Construct(_1); + *(MR.CS.CSharp.ConvCtorExposed *)_UnderlyingPtr = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; } /// @@ -15304,8 +15304,8 @@ public struct ConvCtorExposed public unsafe ConvCtorExposed(int _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ConvCtorExposed_Construct", ExactSpelling = true)] - extern static MR.CS.CSharp.ConvCtorExposed __MR_CSharp_ConvCtorExposed_Construct(int _1); - this = __MR_CSharp_ConvCtorExposed_Construct(_1); + extern static int __MR_CSharp_ConvCtorExposed_Construct(int _1); + this = new MR.CS.CSharp.ConvCtorExposed {x = __MR_CSharp_ConvCtorExposed_Construct(_1)}; } /// @@ -17526,9 +17526,9 @@ public unsafe ConstBox_ExposedLayoutB(ConstBox_ExposedLayoutB _other) : this(nul public unsafe ConstBox_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -17538,9 +17538,9 @@ public unsafe ConstBox_ExposedLayoutB(int _1, int _2) : this(null, is_owning: tr public unsafe ConstBox_ExposedLayoutB(MR.CS.CSharp.Const_A _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -17625,9 +17625,9 @@ public unsafe Box_ExposedLayoutB(ConstBox_ExposedLayoutB _other) : this(null, is public unsafe Box_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -17637,9 +17637,9 @@ public unsafe Box_ExposedLayoutB(int _1, int _2) : this(null, is_owning: true) public unsafe Box_ExposedLayoutB(MR.CS.CSharp.Const_A _1) : this(null, is_owning: true) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); _UnderlyingPtr = (_Underlying *)MR.CS.Misc._Alloc(4); - *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + *(MR.CS.CSharp.ExposedLayoutB *)_UnderlyingPtr = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -17676,8 +17676,8 @@ public struct ExposedLayoutB : System.IEquatable public unsafe ExposedLayoutB(int _1, int _2) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_2", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); - this = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2); + extern static int __MR_CSharp_ExposedLayoutB_Construct_2(int _1, int _2); + this = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_2(_1, _2)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -17687,8 +17687,8 @@ public unsafe ExposedLayoutB(int _1, int _2) public unsafe ExposedLayoutB(MR.CS.CSharp.Const_A _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_ExposedLayoutB_Construct_1", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutB __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); - this = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr); + extern static int __MR_CSharp_ExposedLayoutB_Construct_1(MR.CS.CSharp.Const_A._Underlying *_1); + this = new MR.CS.CSharp.ExposedLayoutB {x = __MR_CSharp_ExposedLayoutB_Construct_1(_1._UnderlyingPtr)}; } // This gets a lifetime annotation from `--infer-lifetime-constructors`, but it should be a no-op in an exposed struct. @@ -28358,6 +28358,18 @@ public static unsafe ref readonly MR.CS.CSharp.ExposedLayoutSh testExposedCref(i if (__c_ret is not null) return *__c_ret; else return null; } + // Single-field exposed structs are passed through P/Invoke as their only field. This tests by-value parameters and return values. + /// + /// Generated from function `MR::CSharp::test_exposed_c`. + /// Parameter `b` defaults to `{}`. + /// + public static unsafe MR.CS.CSharp.ExposedLayoutC testExposedC(MR.CS.CSharp.ExposedLayoutC a, MR.CS.CSharp._InOpt_ExposedLayoutC b = default) + { + [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_test_exposed_c", ExactSpelling = true)] + extern static int __MR_CSharp_test_exposed_c(int a, MR.CS.CSharp.ExposedLayoutC *b); + return new MR.CS.CSharp.ExposedLayoutC {x = __MR_CSharp_test_exposed_c(a.x, b.HasValue ? &b.Object : null)}; + } + /// /// Generated from function `MR::CSharp::test_optint`. /// Parameter `b` defaults to `MR::CSharp::default_optint`. diff --git a/test/output_csharp_fixed_typedefs_64_only/src/MR/test_declaration_order.cs b/test/output_csharp_fixed_typedefs_64_only/src/MR/test_declaration_order.cs index 99302f26..92a9b9a4 100644 --- a/test/output_csharp_fixed_typedefs_64_only/src/MR/test_declaration_order.cs +++ b/test/output_csharp_fixed_typedefs_64_only/src/MR/test_declaration_order.cs @@ -112,8 +112,8 @@ public unsafe Box_A(ConstBox_A _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.A.B c() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_c", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A.B __MR_DeclOrder_A_c(_Underlying *_this); - return __MR_DeclOrder_A_c(_UnderlyingPtr); + extern static int __MR_DeclOrder_A_c(_Underlying *_this); + return new MR.CS.DeclOrder.A.B {bleh = __MR_DeclOrder_A_c(_UnderlyingPtr)}; } /// @@ -154,10 +154,10 @@ public struct A public unsafe MR.CS.DeclOrder.A.B c() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_c", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A.B __MR_DeclOrder_A_c(MR.CS.DeclOrder.A *_this); + extern static int __MR_DeclOrder_A_c(MR.CS.DeclOrder.A *_this); fixed (MR.CS.DeclOrder.A *__ptr__this = &this) { - return __MR_DeclOrder_A_c(__ptr__this); + return new MR.CS.DeclOrder.A.B {bleh = __MR_DeclOrder_A_c(__ptr__this)}; } } @@ -280,8 +280,8 @@ public unsafe Box_B(ConstBox_B _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.A a() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_B_a", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A __MR_DeclOrder_A_B_a(_Underlying *_this); - return __MR_DeclOrder_A_B_a(_UnderlyingPtr); + extern static int __MR_DeclOrder_A_B_a(_Underlying *_this); + return new MR.CS.DeclOrder.A {blah = __MR_DeclOrder_A_B_a(_UnderlyingPtr)}; } /// @@ -321,10 +321,10 @@ public struct B public unsafe MR.CS.DeclOrder.A a() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_A_B_a", ExactSpelling = true)] - extern static MR.CS.DeclOrder.A __MR_DeclOrder_A_B_a(MR.CS.DeclOrder.A.B *_this); + extern static int __MR_DeclOrder_A_B_a(MR.CS.DeclOrder.A.B *_this); fixed (MR.CS.DeclOrder.A.B *__ptr__this = &this) { - return __MR_DeclOrder_A_B_a(__ptr__this); + return new MR.CS.DeclOrder.A {blah = __MR_DeclOrder_A_B_a(__ptr__this)}; } } @@ -603,8 +603,8 @@ public unsafe Box_C_False(ConstBox_C_False _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.C_True blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_false_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_True __MR_DeclOrder_C_false_blah(_Underlying *_this); - return __MR_DeclOrder_C_false_blah(_UnderlyingPtr); + extern static int __MR_DeclOrder_C_false_blah(_Underlying *_this); + return new MR.CS.DeclOrder.C_True {bleh = __MR_DeclOrder_C_false_blah(_UnderlyingPtr)}; } } @@ -634,10 +634,10 @@ public struct C_False public unsafe MR.CS.DeclOrder.C_True blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_false_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_True __MR_DeclOrder_C_false_blah(MR.CS.DeclOrder.C_False *_this); + extern static int __MR_DeclOrder_C_false_blah(MR.CS.DeclOrder.C_False *_this); fixed (MR.CS.DeclOrder.C_False *__ptr__this = &this) { - return __MR_DeclOrder_C_false_blah(__ptr__this); + return new MR.CS.DeclOrder.C_True {bleh = __MR_DeclOrder_C_false_blah(__ptr__this)}; } } } @@ -823,8 +823,8 @@ public unsafe Box_C_True(ConstBox_C_True _other) : this(null, is_owning: true) public unsafe MR.CS.DeclOrder.C_False blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_true_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_False __MR_DeclOrder_C_true_blah(_Underlying *_this); - return __MR_DeclOrder_C_true_blah(_UnderlyingPtr); + extern static int __MR_DeclOrder_C_true_blah(_Underlying *_this); + return new MR.CS.DeclOrder.C_False {bleh = __MR_DeclOrder_C_true_blah(_UnderlyingPtr)}; } } @@ -854,10 +854,10 @@ public struct C_True public unsafe MR.CS.DeclOrder.C_False blah() { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_DeclOrder_C_true_blah", ExactSpelling = true)] - extern static MR.CS.DeclOrder.C_False __MR_DeclOrder_C_true_blah(MR.CS.DeclOrder.C_True *_this); + extern static int __MR_DeclOrder_C_true_blah(MR.CS.DeclOrder.C_True *_this); fixed (MR.CS.DeclOrder.C_True *__ptr__this = &this) { - return __MR_DeclOrder_C_true_blah(__ptr__this); + return new MR.CS.DeclOrder.C_False {bleh = __MR_DeclOrder_C_true_blah(__ptr__this)}; } } } diff --git a/test/output_csharp_fixed_typedefs_64_only/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs b/test/output_csharp_fixed_typedefs_64_only/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs index dc86ac14..4018f136 100644 --- a/test/output_csharp_fixed_typedefs_64_only/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs +++ b/test/output_csharp_fixed_typedefs_64_only/src/std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC.cs @@ -75,22 +75,22 @@ public static unsafe implicit operator bool(MR.CS.Std.Const_Function_MRCSharpExp public unsafe MR.CS.CSharp.ExposedLayoutC call(MR.CS.CSharp.ExposedLayoutC _1) { [System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call", ExactSpelling = true)] - extern static MR.CS.CSharp.ExposedLayoutC __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_Underlying *_this, MR.CS.CSharp.ExposedLayoutC _1); - return __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_UnderlyingPtr, _1); + extern static int __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_Underlying *_this, int _1); + return new MR.CS.CSharp.ExposedLayoutC {x = __MR_C_std_function_MR_CSharp_ExposedLayoutC_from_MR_CSharp_ExposedLayoutC_call(_UnderlyingPtr, _1.x)}; } // Custom extras: public delegate MR.CS.CSharp.ExposedLayoutC Delegate(ref readonly MR.CS.CSharp.ExposedLayoutC _1); - private protected unsafe delegate MR.CS.CSharp.ExposedLayoutC _CDelegate(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value); + private protected unsafe delegate int _CDelegate(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value); - private protected static unsafe MR.CS.CSharp.ExposedLayoutC _CCallWrapper(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value) + private protected static unsafe int _CCallWrapper(MR.CS.CSharp.ExposedLayoutC *_1, void *_userdata, void **_cleanup_value) { ref readonly MR.CS.CSharp.ExposedLayoutC _arg_1 = ref *(MR.CS.CSharp.ExposedLayoutC *)sizeof(MR.CS.CSharp.ExposedLayoutC); // Uninitialized ref. _arg_1 = ref *_1; MR.CS.CSharp.ExposedLayoutC _ret = ((Delegate)System.Runtime.InteropServices.GCHandle.FromIntPtr((nint)_userdata).Target!)(in _arg_1); - return _ret; + return _ret.x; } ///