Browse Source

Fixed handling of primitive pointer types.

pull/225/head
Elias Holzer 11 years ago
parent
commit
d8b855bfe6
  1. 28
      src/AST/TypeExtensions.cs
  2. 8
      src/Generator/Generators/CLI/CLIMarshal.cs
  3. 24
      src/Generator/Generators/CLI/CLITypePrinter.cs
  4. 22
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  5. 12
      tests/Basic/Basic.Tests.cs
  6. 5
      tests/Basic/Basic.cpp
  7. 6
      tests/Basic/Basic.h

28
src/AST/TypeExtensions.cs

@ -154,6 +154,34 @@
} }
return t; return t;
}
public static Type GetFinalPointee(this PointerType pointer)
{
var pointee = pointer.Pointee;
while (pointee.IsPointer())
{
var p = pointee as PointerType;
if (p != null)
pointee = p.Pointee;
else
return GetFinalPointee(pointee as MemberPointerType);
}
return pointee;
}
public static Type GetFinalPointee(this MemberPointerType pointer)
{
var pointee = pointer.Pointee;
while (pointee.IsPointer())
{
var p = pointee as MemberPointerType;
if (p != null)
pointee = p.Pointee;
else
return GetFinalPointee(pointee as PointerType);
}
return pointee;
} }
} }
} }

8
src/Generator/Generators/CLI/CLIMarshal.cs

@ -427,10 +427,10 @@ namespace CppSharp.Generators.CLI
if (Context.Function == null) if (Context.Function == null)
Context.Return.Write("&"); Context.Return.Write("&");
return pointee.Visit(this, quals); return pointee.Visit(this, quals);
} }
PrimitiveType primitive; var finalPointee = pointer.GetFinalPointee();
if (pointee.IsPrimitiveType(out primitive)) if (finalPointee.IsPrimitiveType())
{ {
var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase); var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase);
var cppTypeName = pointer.Visit(cppTypePrinter, quals); var cppTypeName = pointer.Visit(cppTypePrinter, quals);

24
src/Generator/Generators/CLI/CLITypePrinter.cs

@ -140,16 +140,24 @@ namespace CppSharp.Generators.CLI
if (pointee.IsPrimitiveType(PrimitiveType.Char) && quals.IsConst) if (pointee.IsPrimitiveType(PrimitiveType.Char) && quals.IsConst)
{ {
return "System::String^"; return "System::String^";
} }
PrimitiveType primitive; // From http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx
if (pointee.Desugar().IsPrimitiveType(out primitive)) // Any of the following types may be a pointer type:
// * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
// * Any enum type.
// * Any pointer type.
// * Any user-defined struct type that contains fields of unmanaged types only.
var finalPointee = pointer.GetFinalPointee();
if (finalPointee.IsPrimitiveType())
{ {
var param = Context.Parameter; // Skip one indirection if passed by reference
if (param != null && (param.IsOut || param.IsInOut)) var param = Context.Parameter;
return VisitPrimitiveType(primitive); if (param != null && (param.IsOut || param.IsInOut)
&& pointee == finalPointee)
return pointee.Visit(this, quals);
return VisitPrimitiveType(primitive, quals) + "*"; return pointee.Visit(this, quals) + "*";
} }
return pointee.Visit(this, quals); return pointee.Visit(this, quals);

22
src/Generator/Generators/CSharp/CSharpTypePrinter.cs

@ -208,21 +208,29 @@ namespace CppSharp.Generators.CSharp
if (IsConstCharString(pointer)) if (IsConstCharString(pointer))
return isManagedContext ? "string" : "global::System.IntPtr"; return isManagedContext ? "string" : "global::System.IntPtr";
PrimitiveType primitive; // From http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx
var desugared = pointee.Desugar(); // Any of the following types may be a pointer type:
if (desugared.IsPrimitiveType(out primitive)) // * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
// * Any enum type.
// * Any pointer type.
// * Any user-defined struct type that contains fields of unmanaged types only.
var finalPointee = pointer.GetFinalPointee();
if (finalPointee.IsPrimitiveType())
{ {
if (isManagedContext && Context.Parameter != null && // Skip one indirection if passed by reference
(Context.Parameter.IsOut || Context.Parameter.IsInOut)) var param = Context.Parameter;
return VisitPrimitiveType(primitive, quals); if (isManagedContext && param != null && (param.IsOut || param.IsInOut)
&& pointee == finalPointee)
return pointee.Visit(this, quals);
if (ContextKind == CSharpTypePrinterContextKind.GenericDelegate) if (ContextKind == CSharpTypePrinterContextKind.GenericDelegate)
return "global::System.IntPtr"; return "global::System.IntPtr";
return VisitPrimitiveType(primitive, quals) + "*"; return pointee.Visit(this, quals) + "*";
} }
Class @class; Class @class;
var desugared = pointee.Desugar();
if ((desugared.IsDependent || desugared.IsTagDecl(out @class)) if ((desugared.IsDependent || desugared.IsTagDecl(out @class))
&& ContextKind == CSharpTypePrinterContextKind.Native) && ContextKind == CSharpTypePrinterContextKind.Native)
{ {

12
tests/Basic/Basic.Tests.cs

@ -22,7 +22,17 @@ public class BasicTests : GeneratorTestFixture
Assert.That(hello.AddFoo(foo), Is.EqualTo(11)); Assert.That(hello.AddFoo(foo), Is.EqualTo(11));
Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11)); Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11));
Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11)); Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11));
Assert.That(hello.AddFooRef(foo), Is.EqualTo(11)); Assert.That(hello.AddFooRef(foo), Is.EqualTo(11));
unsafe
{
var pointer = foo.SomePointer;
var pointerPointer = foo.SomePointerPointer;
for (int i = 0; i < 4; i++)
{
Assert.AreEqual(i, pointer[i]);
Assert.AreEqual(i, (*pointerPointer)[i]);
}
}
var bar = new Bar { A = 4, B = 7 }; var bar = new Bar { A = 4, B = 7 };
Assert.That(hello.AddBar(bar), Is.EqualTo(11)); Assert.That(hello.AddBar(bar), Is.EqualTo(11));

5
tests/Basic/Basic.cpp

@ -2,6 +2,11 @@
Foo::Foo() Foo::Foo()
{ {
auto p = new int[4];
for (int i = 0; i < 4; i++)
p[i] = i;
SomePointer = p;
SomePointerPointer = &SomePointer;
} }
const char* Foo::GetANSI() const char* Foo::GetANSI()

6
tests/Basic/Basic.h

@ -18,7 +18,11 @@ public:
// TODO: VC++ does not support char16 // TODO: VC++ does not support char16
// char16 chr16; // char16 chr16;
float nested_array[2][2]; // Not properly handled yet - ignore
float nested_array[2][2];
// Primitive pointer types
int* SomePointer;
int** SomePointerPointer;
}; };
struct DLL_API Bar struct DLL_API Bar

Loading…
Cancel
Save