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. 4
      src/Generator/Generators/CLI/CLIMarshal.cs
  3. 20
      src/Generator/Generators/CLI/CLITypePrinter.cs
  4. 24
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  5. 10
      tests/Basic/Basic.Tests.cs
  6. 5
      tests/Basic/Basic.cpp
  7. 4
      tests/Basic/Basic.h

28
src/AST/TypeExtensions.cs

@ -155,5 +155,33 @@
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;
}
} }
} }

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

@ -429,8 +429,8 @@ namespace CppSharp.Generators.CLI
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);

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

@ -142,14 +142,22 @@ namespace CppSharp.Generators.CLI
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())
{
// Skip one indirection if passed by reference
var param = Context.Parameter; var param = Context.Parameter;
if (param != null && (param.IsOut || param.IsInOut)) if (param != null && (param.IsOut || param.IsInOut)
return VisitPrimitiveType(primitive); && 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);

24
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.
if (isManagedContext && Context.Parameter != null && // * Any pointer type.
(Context.Parameter.IsOut || Context.Parameter.IsInOut)) // * Any user-defined struct type that contains fields of unmanaged types only.
return VisitPrimitiveType(primitive, quals); var finalPointee = pointer.GetFinalPointee();
if (finalPointee.IsPrimitiveType())
{
// Skip one indirection if passed by reference
var param = Context.Parameter;
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)
{ {

10
tests/Basic/Basic.Tests.cs

@ -23,6 +23,16 @@ public class BasicTests : GeneratorTestFixture
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()

4
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;
// Not properly handled yet - ignore
float nested_array[2][2]; float nested_array[2][2];
// Primitive pointer types
int* SomePointer;
int** SomePointerPointer;
}; };
struct DLL_API Bar struct DLL_API Bar

Loading…
Cancel
Save