Browse Source

Fix the getting of references to pointers in C#

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
bug-pass-const-char-star-no-copy
Dimitar Dobrev 6 years ago
parent
commit
1792f529ff
  1. 28
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 9
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 6
      tests/CSharp/CSharp.Tests.cs
  4. 7
      tests/CSharp/CSharp.cpp
  5. 3
      tests/CSharp/CSharp.h

28
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -146,13 +146,25 @@ namespace CppSharp.Generators.CSharp
var pointee = pointer.Pointee.Desugar(); var pointee = pointer.Pointee.Desugar();
var finalPointee = pointer.GetFinalPointee().Desugar(); var finalPointee = pointer.GetFinalPointee().Desugar();
var type = Context.ReturnType.Type.Desugar( var returnType = Context.ReturnType.Type.Desugar(
resolveTemplateSubstitution: false); resolveTemplateSubstitution: false);
PrimitiveType primitive; if ((pointee.IsConstCharString() && (isRefParam || returnType.IsReference())) ||
if ((pointee.IsConstCharString() && (isRefParam || type.IsReference())) || (!finalPointee.IsPrimitiveType(out PrimitiveType primitive) &&
(!finalPointee.IsPrimitiveType(out primitive) &&
!finalPointee.IsEnumType())) !finalPointee.IsEnumType()))
{
if (Context.MarshalKind != MarshalKind.NativeField &&
pointee.IsPointerTo(out Type type) &&
type.Desugar().TryGetClass(out Class c))
{
string ret = Generator.GeneratedIdentifier(Context.ReturnVarName);
Context.Before.WriteLine($@"{typePrinter.IntPtrType} {ret} = {
Context.ReturnVarName} == {typePrinter.IntPtrType}.Zero ? {
typePrinter.IntPtrType}.Zero : new {
typePrinter.IntPtrType}(*(void**) {Context.ReturnVarName});");
Context.ReturnVarName = ret;
}
return pointer.QualifiedPointee.Visit(this); return pointer.QualifiedPointee.Visit(this);
}
if (isRefParam) if (isRefParam)
{ {
@ -167,7 +179,7 @@ namespace CppSharp.Generators.CSharp
if (Context.Function != null && if (Context.Function != null &&
Context.Function.OperatorKind == CXXOperatorKind.Subscript) Context.Function.OperatorKind == CXXOperatorKind.Subscript)
{ {
if (type.IsPrimitiveType(primitive)) if (returnType.IsPrimitiveType(primitive))
{ {
Context.Return.Write("*"); Context.Return.Write("*");
} }
@ -517,7 +529,7 @@ namespace CppSharp.Generators.CSharp
if (param.IsOut) if (param.IsOut)
{ {
MarshalString(pointee); MarshalString(pointee);
Context.Return.Write("IntPtr.Zero"); Context.Return.Write($"{typePrinter.IntPtrType}.Zero");
Context.ArgumentPrefix.Write("&"); Context.ArgumentPrefix.Write("&");
return true; return true;
} }
@ -604,7 +616,7 @@ namespace CppSharp.Generators.CSharp
arg, Context.Parameter.Name, Helpers.InstanceIdentifier); arg, Context.Parameter.Name, Helpers.InstanceIdentifier);
} }
Context.Return.Write($"new global::System.IntPtr(&{arg})"); Context.Return.Write($"new {typePrinter.IntPtrType}(&{arg})");
return true; return true;
} }
@ -614,7 +626,7 @@ namespace CppSharp.Generators.CSharp
pointer.QualifiedPointee.Visit(this); pointer.QualifiedPointee.Visit(this);
Context.Before.WriteLine($"var {arg} = {Context.Return};"); Context.Before.WriteLine($"var {arg} = {Context.Return};");
Context.Return.StringBuilder.Clear(); Context.Return.StringBuilder.Clear();
Context.Return.Write($"new global::System.IntPtr(&{arg})"); Context.Return.Write($"new {typePrinter.IntPtrType}(&{arg})");
return true; return true;
} }

9
src/Generator/Generators/CSharp/CSharpSources.cs

@ -1741,15 +1741,16 @@ namespace CppSharp.Generators.CSharp
} }
} }
bool isVoid = method.OriginalReturnType.Type.Desugar().IsPrimitiveType( Type returnType = method.OriginalReturnType.Type.Desugar();
PrimitiveType.Void); bool isPrimitive = returnType.IsPrimitiveType();
bool isVoid = returnType.IsPrimitiveType(PrimitiveType.Void);
var property = ((Class) method.Namespace).Properties.Find( var property = ((Class) method.Namespace).Properties.Find(
p => p.GetMethod == method || p.SetMethod == method); p => p.GetMethod == method || p.SetMethod == method);
bool isSetter = property != null && property.SetMethod == method; bool isSetter = property != null && property.SetMethod == method;
var hasReturn = !isVoid && !isSetter; var hasReturn = !isVoid && !isSetter;
if (hasReturn) if (hasReturn)
Write($"var {Helpers.ReturnIdentifier} = "); Write(isPrimitive && !isSetter ? "return " : $"var {Helpers.ReturnIdentifier} = ");
Write($"{Helpers.TargetIdentifier}."); Write($"{Helpers.TargetIdentifier}.");
string marshalsCode = string.Join(", ", marshals); string marshalsCode = string.Join(", ", marshals);
@ -1764,6 +1765,8 @@ namespace CppSharp.Generators.CSharp
Write($" = {marshalsCode}"); Write($" = {marshalsCode}");
} }
WriteLine(";"); WriteLine(";");
if (isPrimitive && !isSetter)
return;
if (hasReturn) if (hasReturn)
{ {

6
tests/CSharp/CSharp.Tests.cs

@ -1285,8 +1285,12 @@ public unsafe class CSharpTests : GeneratorTestFixture
{ {
using (Foo foo = new Foo { A = 25 }) using (Foo foo = new Foo { A = 25 })
{ {
Foo returnedFoo = CSharp.CSharp.TakeRefToPointerToObject(foo); Foo returnedFoo = CSharp.CSharp.TakeReturnReferenceToPointer(foo);
Assert.That(returnedFoo.A, Is.EqualTo(foo.A)); Assert.That(returnedFoo.A, Is.EqualTo(foo.A));
using (Qux qux = new Qux())
{
Assert.That(qux.TakeReferenceToPointer(foo), Is.EqualTo(foo.A));
}
} }
} }

7
tests/CSharp/CSharp.cpp

@ -225,6 +225,11 @@ void Qux::makeClassDynamic()
{ {
} }
int Qux::takeReferenceToPointer(Foo*& ret)
{
return ret->A;
}
Bar::Bar(Qux qux) Bar::Bar(Qux qux)
{ {
} }
@ -1623,7 +1628,7 @@ const void*& rValueReferenceToPointer(void*&& v)
return (const void*&) v; return (const void*&) v;
} }
const Foo* takeRefToPointerToObject(const Foo*& foo) const Foo*& takeReturnReferenceToPointer(const Foo*& foo)
{ {
return foo; return foo;
} }

3
tests/CSharp/CSharp.h

@ -84,6 +84,7 @@ public:
Qux* getInterface(); Qux* getInterface();
void setInterface(Qux* qux); void setInterface(Qux* qux);
virtual void makeClassDynamic(); virtual void makeClassDynamic();
virtual int takeReferenceToPointer(Foo*& ret);
}; };
class DLL_API Bar : public Qux class DLL_API Bar : public Qux
@ -1325,7 +1326,7 @@ DLL_API char* returnCharPointer();
DLL_API char* takeConstCharRef(const char& c); DLL_API char* takeConstCharRef(const char& c);
DLL_API const char*& takeConstCharStarRef(const char*& c); DLL_API const char*& takeConstCharStarRef(const char*& c);
DLL_API const void*& rValueReferenceToPointer(void*&& v); DLL_API const void*& rValueReferenceToPointer(void*&& v);
DLL_API const Foo* takeRefToPointerToObject(const Foo*& foo); DLL_API const Foo*& takeReturnReferenceToPointer(const Foo*& foo);
struct { struct {
struct { struct {

Loading…
Cancel
Save