Skip to content

Commit eb0d4c1

Browse files
jpnoirtritao
authored andcommitted
bug fix: When generating the get accessor for a field composed of an embedded array of structs use __GetOrCreateInstance to initialize the managed array wrapper rather than __CreateInstance so that __Instance holds a pointer to the memory allocated for the array in the outer struct rather than an independent copy of that memory.
Added a test. TODO: once allocated, we may want to cache the managed array. Does this issue exist in other generators as well?
1 parent d135ffd commit eb0d4c1

File tree

4 files changed

+20
-3
lines changed

4 files changed

+20
-3
lines changed

src/Generator/Generators/CSharp/CSharpMarshal.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
9191
{
9292
if (arrayType == finalArrayType)
9393
supportBefore.WriteLineIndent(
94-
"{0}[i] = {1}.{2}(*(({1}.{3}*)&({4}[i * sizeof({1}.{3})])));",
95-
value, array.Type, Helpers.CreateInstanceIdentifier,
94+
"{0}[i] = {1}.{2}((IntPtr)(({1}.{3}*)&({4}[i * sizeof({1}.{3})])), true, true);",
95+
value, array.Type, Helpers.GetOrCreateInstanceIdentifier,
9696
Helpers.InternalStruct, Context.ReturnVarName);
9797
else
9898
supportBefore.WriteLineIndent(

src/Generator/Generators/CodeGenerator.cs

+1
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,7 @@ public static class Helpers
13011301
public static readonly string OwnsNativeInstanceIdentifier = Generator.GeneratedIdentifier("ownsNativeInstance");
13021302

13031303
public static readonly string CreateInstanceIdentifier = Generator.GeneratedIdentifier("CreateInstance");
1304+
public static readonly string GetOrCreateInstanceIdentifier = Generator.GeneratedIdentifier("GetOrCreateInstance");
13041305

13051306
public static string GetSuffixForInternal(DeclarationContext @class)
13061307
{

tests/CSharp/CSharp.Tests.cs

+16
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,22 @@ public void TestAlignment()
767767
}
768768
}
769769

770+
[Test]
771+
public void TestEmbeddedArrayOfStructAccessor()
772+
{
773+
const ulong firstLong = 0xC92EEDE87AAB4FECul;
774+
const ulong secondLong = 0xAD5FB16491935522ul;
775+
776+
var testStruct = new StructWithEmbeddedArrayOfStructObjectAlignment();
777+
testStruct.EmbeddedStruct[0].Ui64 = firstLong;
778+
testStruct.EmbeddedStruct[1].Ui64 = secondLong;
779+
780+
// Since the memory allocated for EmbeddedStruct is generally uninintialized, I suppose it _could_
781+
// just happen to match, but it seems very unlikely.
782+
Assert.That(firstLong, Is.EqualTo(testStruct.EmbeddedStruct[0].Ui64));
783+
Assert.That(secondLong, Is.EqualTo(testStruct.EmbeddedStruct[1].Ui64));
784+
}
785+
770786
public void TestClassSize()
771787
{
772788
Assert.That(Marshal.SizeOf<HasSecondaryBaseWithAbstractWithDefaultArg.__Internal>, Is.EqualTo(Marshal.SizeOf<IntPtr>() * 2));

tests/CSharp/CSharp.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1504,7 +1504,7 @@ struct DLL_API ClassMicrosoftObjectAlignment : ClassMicrosoftObjectAlignmentBase
15041504

15051505
struct DLL_API EmbeddedStruct
15061506
{
1507-
int64_t i64;
1507+
uint64_t ui64;
15081508
};
15091509
struct DLL_API StructWithEmbeddedArrayOfStructObjectAlignment
15101510
{

0 commit comments

Comments
 (0)