Skip to content

Commit 1792f52

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

File tree

5 files changed

+39
-14
lines changed

5 files changed

+39
-14
lines changed

src/Generator/Generators/CSharp/CSharpMarshal.cs

+20-8
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,25 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
146146

147147
var pointee = pointer.Pointee.Desugar();
148148
var finalPointee = pointer.GetFinalPointee().Desugar();
149-
var type = Context.ReturnType.Type.Desugar(
149+
var returnType = Context.ReturnType.Type.Desugar(
150150
resolveTemplateSubstitution: false);
151-
PrimitiveType primitive;
152-
if ((pointee.IsConstCharString() && (isRefParam || type.IsReference())) ||
153-
(!finalPointee.IsPrimitiveType(out primitive) &&
151+
if ((pointee.IsConstCharString() && (isRefParam || returnType.IsReference())) ||
152+
(!finalPointee.IsPrimitiveType(out PrimitiveType primitive) &&
154153
!finalPointee.IsEnumType()))
154+
{
155+
if (Context.MarshalKind != MarshalKind.NativeField &&
156+
pointee.IsPointerTo(out Type type) &&
157+
type.Desugar().TryGetClass(out Class c))
158+
{
159+
string ret = Generator.GeneratedIdentifier(Context.ReturnVarName);
160+
Context.Before.WriteLine($@"{typePrinter.IntPtrType} {ret} = {
161+
Context.ReturnVarName} == {typePrinter.IntPtrType}.Zero ? {
162+
typePrinter.IntPtrType}.Zero : new {
163+
typePrinter.IntPtrType}(*(void**) {Context.ReturnVarName});");
164+
Context.ReturnVarName = ret;
165+
}
155166
return pointer.QualifiedPointee.Visit(this);
167+
}
156168

157169
if (isRefParam)
158170
{
@@ -167,7 +179,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
167179
if (Context.Function != null &&
168180
Context.Function.OperatorKind == CXXOperatorKind.Subscript)
169181
{
170-
if (type.IsPrimitiveType(primitive))
182+
if (returnType.IsPrimitiveType(primitive))
171183
{
172184
Context.Return.Write("*");
173185
}
@@ -517,7 +529,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
517529
if (param.IsOut)
518530
{
519531
MarshalString(pointee);
520-
Context.Return.Write("IntPtr.Zero");
532+
Context.Return.Write($"{typePrinter.IntPtrType}.Zero");
521533
Context.ArgumentPrefix.Write("&");
522534
return true;
523535
}
@@ -604,7 +616,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
604616
arg, Context.Parameter.Name, Helpers.InstanceIdentifier);
605617
}
606618

607-
Context.Return.Write($"new global::System.IntPtr(&{arg})");
619+
Context.Return.Write($"new {typePrinter.IntPtrType}(&{arg})");
608620
return true;
609621
}
610622

@@ -614,7 +626,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
614626
pointer.QualifiedPointee.Visit(this);
615627
Context.Before.WriteLine($"var {arg} = {Context.Return};");
616628
Context.Return.StringBuilder.Clear();
617-
Context.Return.Write($"new global::System.IntPtr(&{arg})");
629+
Context.Return.Write($"new {typePrinter.IntPtrType}(&{arg})");
618630
return true;
619631
}
620632

src/Generator/Generators/CSharp/CSharpSources.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1741,15 +1741,16 @@ private void GenerateVTableManagedCall(Method method)
17411741
}
17421742
}
17431743

1744-
bool isVoid = method.OriginalReturnType.Type.Desugar().IsPrimitiveType(
1745-
PrimitiveType.Void);
1744+
Type returnType = method.OriginalReturnType.Type.Desugar();
1745+
bool isPrimitive = returnType.IsPrimitiveType();
1746+
bool isVoid = returnType.IsPrimitiveType(PrimitiveType.Void);
17461747
var property = ((Class) method.Namespace).Properties.Find(
17471748
p => p.GetMethod == method || p.SetMethod == method);
17481749
bool isSetter = property != null && property.SetMethod == method;
17491750
var hasReturn = !isVoid && !isSetter;
17501751

17511752
if (hasReturn)
1752-
Write($"var {Helpers.ReturnIdentifier} = ");
1753+
Write(isPrimitive && !isSetter ? "return " : $"var {Helpers.ReturnIdentifier} = ");
17531754

17541755
Write($"{Helpers.TargetIdentifier}.");
17551756
string marshalsCode = string.Join(", ", marshals);
@@ -1764,6 +1765,8 @@ private void GenerateVTableManagedCall(Method method)
17641765
Write($" = {marshalsCode}");
17651766
}
17661767
WriteLine(";");
1768+
if (isPrimitive && !isSetter)
1769+
return;
17671770

17681771
if (hasReturn)
17691772
{

tests/CSharp/CSharp.Tests.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1285,8 +1285,12 @@ public void TakeRefToPointerToObject()
12851285
{
12861286
using (Foo foo = new Foo { A = 25 })
12871287
{
1288-
Foo returnedFoo = CSharp.CSharp.TakeRefToPointerToObject(foo);
1288+
Foo returnedFoo = CSharp.CSharp.TakeReturnReferenceToPointer(foo);
12891289
Assert.That(returnedFoo.A, Is.EqualTo(foo.A));
1290+
using (Qux qux = new Qux())
1291+
{
1292+
Assert.That(qux.TakeReferenceToPointer(foo), Is.EqualTo(foo.A));
1293+
}
12901294
}
12911295
}
12921296

tests/CSharp/CSharp.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ void Qux::makeClassDynamic()
225225
{
226226
}
227227

228+
int Qux::takeReferenceToPointer(Foo*& ret)
229+
{
230+
return ret->A;
231+
}
232+
228233
Bar::Bar(Qux qux)
229234
{
230235
}
@@ -1623,7 +1628,7 @@ const void*& rValueReferenceToPointer(void*&& v)
16231628
return (const void*&) v;
16241629
}
16251630

1626-
const Foo* takeRefToPointerToObject(const Foo*& foo)
1631+
const Foo*& takeReturnReferenceToPointer(const Foo*& foo)
16271632
{
16281633
return foo;
16291634
}

tests/CSharp/CSharp.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class DLL_API Qux
8484
Qux* getInterface();
8585
void setInterface(Qux* qux);
8686
virtual void makeClassDynamic();
87+
virtual int takeReferenceToPointer(Foo*& ret);
8788
};
8889

8990
class DLL_API Bar : public Qux
@@ -1325,7 +1326,7 @@ DLL_API char* returnCharPointer();
13251326
DLL_API char* takeConstCharRef(const char& c);
13261327
DLL_API const char*& takeConstCharStarRef(const char*& c);
13271328
DLL_API const void*& rValueReferenceToPointer(void*&& v);
1328-
DLL_API const Foo* takeRefToPointerToObject(const Foo*& foo);
1329+
DLL_API const Foo*& takeReturnReferenceToPointer(const Foo*& foo);
13291330

13301331
struct {
13311332
struct {

0 commit comments

Comments
 (0)