Skip to content

Commit 62fc6f9

Browse files
committed
Fix the passing of references to pointers in C#
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent c051073 commit 62fc6f9

File tree

5 files changed

+42
-12
lines changed

5 files changed

+42
-12
lines changed

src/Generator/Generators/CSharp/CSharpMarshal.cs

+16-7
Original file line numberDiff line numberDiff line change
@@ -587,25 +587,34 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
587587
return true;
588588
}
589589

590+
591+
string arg = Generator.GeneratedIdentifier(Context.ArgName);
592+
590593
if (pointee.TryGetClass(out Class @class) && @class.IsValueType)
591594
{
592595
if (Context.Parameter.Usage == ParameterUsage.Out)
593596
{
594597
var qualifiedIdentifier = (@class.OriginalClass ?? @class).Visit(typePrinter);
595598
Context.Before.WriteLine("var {0} = new {1}.{2}();",
596-
Generator.GeneratedIdentifier(Context.ArgName), qualifiedIdentifier,
597-
Helpers.InternalStruct);
599+
arg, qualifiedIdentifier, Helpers.InternalStruct);
598600
}
599601
else
600602
{
601603
Context.Before.WriteLine("var {0} = {1}.{2};",
602-
Generator.GeneratedIdentifier(Context.ArgName),
603-
Context.Parameter.Name,
604-
Helpers.InstanceIdentifier);
604+
arg, Context.Parameter.Name, Helpers.InstanceIdentifier);
605605
}
606606

607-
Context.Return.Write("new global::System.IntPtr(&{0})",
608-
Generator.GeneratedIdentifier(Context.ArgName));
607+
Context.Return.Write($"new global::System.IntPtr(&{arg})");
608+
return true;
609+
}
610+
611+
if (pointee.IsPointerTo(out Type type) &&
612+
type.Desugar().TryGetClass(out Class c))
613+
{
614+
pointer.QualifiedPointee.Visit(this);
615+
Context.Before.WriteLine($"var {arg} = {Context.Return};");
616+
Context.Return.StringBuilder.Clear();
617+
Context.Return.Write($"new global::System.IntPtr(&{arg})");
609618
return true;
610619
}
611620

src/Generator/Generators/CSharp/CSharpSources.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,8 @@ private void GenerateIndexerSetter(Function function)
10371037
},
10381038
ParameterIndex = function.Parameters.Count(
10391039
p => p.Kind != ParameterKind.IndirectReturnType),
1040-
ReturnType = new QualifiedType(type)
1040+
ReturnType = new QualifiedType(type),
1041+
ArgName = "value"
10411042
};
10421043
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
10431044
type.Visit(marshal);

tests/CSharp/CSharp.Tests.cs

+18-4
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,6 @@ public void TestUncompilableCode()
9494
{
9595
}
9696

97-
int value = 5;
98-
IntPtr intPtr = CSharp.CSharp.RValueReferenceToPointer((void**) &value);
99-
Assert.That((int) intPtr, Is.EqualTo(value));
100-
10197
#pragma warning restore 0168
10298
#pragma warning restore 0219
10399
}
@@ -1276,6 +1272,24 @@ public void TestConstCharStarRef()
12761272
Assert.That(CSharp.CSharp.TakeConstCharStarRef("Test"), Is.EqualTo("Test"));
12771273
}
12781274

1275+
[Test]
1276+
public void TestRValueReferenceToPointer()
1277+
{
1278+
int value = 5;
1279+
IntPtr intPtr = CSharp.CSharp.RValueReferenceToPointer((void**) &value);
1280+
Assert.That((int) intPtr, Is.EqualTo(value));
1281+
}
1282+
1283+
[Test]
1284+
public void TakeRefToPointerToObject()
1285+
{
1286+
using (Foo foo = new Foo { A = 25 })
1287+
{
1288+
Foo returnedFoo = CSharp.CSharp.TakeRefToPointerToObject(foo);
1289+
Assert.That(returnedFoo.A, Is.EqualTo(foo.A));
1290+
}
1291+
}
1292+
12791293
[Test]
12801294
public void TestImplicitConversionToString()
12811295
{

tests/CSharp/CSharp.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,11 @@ const void*& rValueReferenceToPointer(void*&& v)
16231623
return (const void*&) v;
16241624
}
16251625

1626+
const Foo* takeRefToPointerToObject(const Foo*& foo)
1627+
{
1628+
return foo;
1629+
}
1630+
16261631
boolean_t takeTypemapTypedefParam(boolean_t b)
16271632
{
16281633
return b;

tests/CSharp/CSharp.h

+1
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,7 @@ DLL_API char* returnCharPointer();
13251325
DLL_API char* takeConstCharRef(const char& c);
13261326
DLL_API const char*& takeConstCharStarRef(const char*& c);
13271327
DLL_API const void*& rValueReferenceToPointer(void*&& v);
1328+
DLL_API const Foo* takeRefToPointerToObject(const Foo*& foo);
13281329

13291330
struct {
13301331
struct {

0 commit comments

Comments
 (0)