Browse Source

Added support for marshalling arrays of pointers to primitives.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/154/head
Dimitar Dobrev 12 years ago
parent
commit
4c5d933cd2
  1. 35
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 80
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  3. 7
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  4. 3
      src/Generator/Passes/CheckIgnoredDecls.cs
  5. 11
      tests/CSharpTemp/CSharpTemp.Tests.cs
  6. 1
      tests/CSharpTemp/CSharpTemp.h

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

@ -117,17 +117,12 @@ namespace CppSharp.Generators.CSharp @@ -117,17 +117,12 @@ namespace CppSharp.Generators.CSharp
case ArrayType.ArraySize.Constant:
var supportBefore = Context.SupportBefore;
string value = Generator.GeneratedIdentifier("value");
supportBefore.WriteLine("{0}[] {1} = new {0}[{2}];", array.Type, value, array.Size);
string v = Generator.GeneratedIdentifier("v");
supportBefore.WriteLine("fixed ({0}* {1} = {2})", array.Type, v, value);
supportBefore.WriteLine("{0}[] {1} = null;", array.Type, value, array.Size);
supportBefore.WriteLine("if ({0} != null)", Context.ReturnVarName);
supportBefore.WriteStartBraceIndent();
string to = Generator.GeneratedIdentifier("to");
supportBefore.WriteLine("{0}* {1} = {2};", array.Type, to, v);
string from = Generator.GeneratedIdentifier("from");
supportBefore.WriteLine("{0}* {1} = {2};",
array.Type, from, Context.ReturnVarName);
supportBefore.WriteLine("{0} = new {1}[{2}];", value, array.Type, array.Size);
supportBefore.WriteLine("for (int i = 0; i < {0}; i++)", array.Size);
supportBefore.WriteLineIndent("*{0}++ = *{1}++;", to, from);
supportBefore.WriteLineIndent("{0}[i] = {1}[i];", value, Context.ReturnVarName);
supportBefore.WriteCloseBraceIndent();
Context.Return.Write(value);
break;
@ -373,22 +368,12 @@ namespace CppSharp.Generators.CSharp @@ -373,22 +368,12 @@ namespace CppSharp.Generators.CSharp
{
case ArrayType.ArraySize.Constant:
var supportBefore = Context.SupportBefore;
supportBefore.WriteLine("if ({0}.Length != {1})",
Context.ArgName, array.Size);
supportBefore.WriteLineIndent(
"throw new ArgumentException(\"The value must be an array of size {0}.\");",
array.Size);
string v = Generator.GeneratedIdentifier("v");
supportBefore.WriteLine("fixed ({0}* {1} = {2})", array.Type, v, Context.ArgName);
supportBefore.WriteLineIndent("for (int i = 0; i < {0}; i++)", array.Size);
supportBefore.PushIndent();
supportBefore.WriteLineIndent("*({0}->{1} + i) = *({2} + i);",
Generator.GeneratedIdentifier("ptr"), Context.ReturnVarName, v);
supportBefore.PopIndent();
supportBefore.WriteLine("fixed ({0}* {1} = {2})", array.Type, v, Context.ArgName);
supportBefore.PushIndent();
supportBefore.Write("*");
Context.Return.Write("*{0}", v);
supportBefore.WriteLine("if ({0} != null)", Context.ArgName);
supportBefore.WriteStartBraceIndent();
supportBefore.WriteLine("for (int i = 0; i < {0}; i++)", array.Size);
supportBefore.WriteLineIndent("{0}[i] = {1}[i];",
Context.ReturnVarName, Context.ArgName);
supportBefore.WriteCloseBraceIndent();
break;
default:
Context.Return.Write("null");

80
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -639,7 +639,10 @@ namespace CppSharp.Generators.CSharp @@ -639,7 +639,10 @@ namespace CppSharp.Generators.CSharp
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);
WriteLine("{0} = {1};", property.Name, marshal.Context.Return);
if (marshal.Context.Return.StringBuilder.Length > 0)
{
WriteLine("{0} = {1};", property.Name, marshal.Context.Return);
}
}
}
@ -648,6 +651,7 @@ namespace CppSharp.Generators.CSharp @@ -648,6 +651,7 @@ namespace CppSharp.Generators.CSharp
var marshalVar = Generator.GeneratedIdentifier("native");
WriteLine("var {0} = new {1}.Internal();", marshalVar, QualifiedIdentifier(@class));
WriteLine("var {0} = &{1};", Generator.GeneratedIdentifier("ptr"), marshalVar);
GenerateStructInternalMarshalingProperties(@class, marshalVar);
WriteLine("return {0};", marshalVar);
@ -675,9 +679,12 @@ namespace CppSharp.Generators.CSharp @@ -675,9 +679,12 @@ namespace CppSharp.Generators.CSharp
private void GenerateStructInternalMarshalingProperty(Property property, string marshalVar)
{
var nativeField = string.Format("{0}->{1}",
Generator.GeneratedIdentifier("ptr"), property.Field.OriginalName);
var marshalCtx = new CSharpMarshalContext(Driver)
{
ArgName = property.Name,
ReturnVarName = nativeField,
};
var marshal = new CSharpMarshalManagedToNativePrinter(marshalCtx);
@ -698,7 +705,11 @@ namespace CppSharp.Generators.CSharp @@ -698,7 +705,11 @@ namespace CppSharp.Generators.CSharp
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
WriteLine(marshal.Context.SupportBefore);
WriteLine("{0}.{1} = {2};", marshalVar, property.OriginalName, marshal.Context.Return);
if (marshal.Context.Return.StringBuilder.Length > 0)
{
WriteLine("{0}.{1} = {2};", marshalVar,
property.OriginalName, marshal.Context.Return);
}
if (isRef)
WriteCloseBraceIndent();
@ -902,6 +913,9 @@ namespace CppSharp.Generators.CSharp @@ -902,6 +913,9 @@ namespace CppSharp.Generators.CSharp
}
else
{
var field = decl as Field;
if (WrapSetterArrayOfPointers(decl.Name, field.Type))
return;
if (@class.IsValueType)
{
if (@class.IsUnion)
@ -918,28 +932,48 @@ namespace CppSharp.Generators.CSharp @@ -918,28 +932,48 @@ namespace CppSharp.Generators.CSharp
}
WriteStartBraceIndent();
var field = decl as Field;
WriteLine("var {0} = (Internal*){1}.ToPointer();",
Generator.GeneratedIdentifier("ptr"), Helpers.InstanceIdentifier);
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
ctx.ReturnVarName = field.OriginalName;
ctx.ReturnVarName = string.Format("{0}->{1}",
Generator.GeneratedIdentifier("ptr"), Helpers.SafeIdentifier(field.OriginalName));
param.Visit(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);
Write("{0}->{1} = {2}", Generator.GeneratedIdentifier("ptr"),
Helpers.SafeIdentifier(field.OriginalName), marshal.Context.Return);
if (marshal.Context.Return.StringBuilder.Length > 0)
{
WriteLine("{0} = {1};", ctx.ReturnVarName, marshal.Context.Return);
}
WriteLine(";");
WriteCloseBraceIndent();
}
PopBlock(NewLineKind.BeforeNextBlock);
}
private bool WrapSetterArrayOfPointers(string name, Type fieldType)
{
var arrayType = fieldType as ArrayType;
if (arrayType != null && arrayType.Type.IsPointerToPrimitiveType())
{
NewLine();
WriteStartBraceIndent();
WriteLine("{0} = value;", name);
WriteLine("if (!{0}{1})", name, "Initialised");
WriteStartBraceIndent();
WriteLine("{0}{1} = true;", name, "Initialised");
WriteCloseBraceIndent();
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
return true;
}
return false;
}
private void GenerateIndexerSetter(QualifiedType returnType, Function function)
{
Type type;
@ -995,6 +1029,9 @@ namespace CppSharp.Generators.CSharp @@ -995,6 +1029,9 @@ namespace CppSharp.Generators.CSharp
}
else if (decl is Field)
{
var field = decl as Field;
if (WrapGetterArrayOfPointers(decl.Name, field.Type))
return;
if (@class.IsValueType)
{
if (@class.IsUnion)
@ -1013,7 +1050,6 @@ namespace CppSharp.Generators.CSharp @@ -1013,7 +1050,6 @@ namespace CppSharp.Generators.CSharp
NewLine();
WriteStartBraceIndent();
var field = decl as Field;
WriteLine("var {0} = (Internal*){1}.ToPointer();",
Generator.GeneratedIdentifier("ptr"), Helpers.InstanceIdentifier);
@ -1072,6 +1108,26 @@ namespace CppSharp.Generators.CSharp @@ -1072,6 +1108,26 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock);
}
private bool WrapGetterArrayOfPointers(string name, Type fieldType)
{
var arrayType = fieldType as ArrayType;
if (arrayType != null && arrayType.Type.IsPointerToPrimitiveType())
{
NewLine();
WriteStartBraceIndent();
WriteLine("if (!{0}{1})", name, "Initialised");
WriteStartBraceIndent();
WriteLine("{0} = null;", name);
WriteLine("{0}{1} = true;", name, "Initialised");
WriteCloseBraceIndent();
WriteLine("return {0};", name);
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
return true;
}
return false;
}
public void GenerateClassMethods(Class @class)
{
var staticMethods = new List<Method>();
@ -1144,6 +1200,14 @@ namespace CppSharp.Generators.CSharp @@ -1144,6 +1200,14 @@ namespace CppSharp.Generators.CSharp
if (prop.Parameters.Count > 0 && prop.Type.IsPointerToPrimitiveType())
type = ((PointerType) prop.Type).Pointee;
ArrayType arrayType = prop.Type as ArrayType;
if (arrayType != null && arrayType.Type.IsPointerToPrimitiveType() && prop.Field != null)
{
GenerateClassField(prop.Field);
WriteLine("private bool {0};",
GeneratedIdentifier(string.Format("{0}Initialised", prop.Field.OriginalName)));
}
GenerateDeclarationCommon(prop);
if (prop.ExplicitInterfaceImpl == null)
{

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

@ -113,6 +113,13 @@ namespace CppSharp.Generators.CSharp @@ -113,6 +113,13 @@ namespace CppSharp.Generators.CSharp
if (ContextKind == CSharpTypePrinterContextKind.Native &&
array.SizeType == ArrayType.ArraySize.Constant)
{
if (array.Type.Desugar().IsPointerToPrimitiveType())
{
return new CSharpTypePrinterResult
{
Type = string.Format("{0}*", array.Type.Visit(this, quals))
};
}
return new CSharpTypePrinterResult()
{
Type = string.Format("fixed {0}", array.Type.Visit(this, quals)),

3
src/Generator/Passes/CheckIgnoredDecls.cs

@ -338,7 +338,8 @@ namespace CppSharp.Passes @@ -338,7 +338,8 @@ namespace CppSharp.Passes
var arrayType = type as ArrayType;
PrimitiveType primitive;
if (arrayType != null && arrayType.SizeType == ArrayType.ArraySize.Constant &&
!arrayType.Type.Desugar().IsPrimitiveType(out primitive))
!arrayType.Type.Desugar().IsPrimitiveType(out primitive) &&
!arrayType.Type.Desugar().IsPointerToPrimitiveType())
{
msg = "unsupported";
return true;

11
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -96,4 +96,15 @@ public class CSharpTempTests : GeneratorTestFixture @@ -96,4 +96,15 @@ public class CSharpTempTests : GeneratorTestFixture
dtors.Dispose();
Assert.AreEqual(0xcafe, CSharpTemp.TestDestructors.Marker);
}
[Test]
public unsafe void TestArrayOfPointersToPrimitives()
{
Bar bar = new Bar();
void*[] array = new void*[1];
int i = 5;
array[0] = &i;
bar.ArrayOfPrimitivePointers = array;
Assert.That(i, Is.EqualTo(*(int*) bar.ArrayOfPrimitivePointers[0]));
}
}

1
tests/CSharpTemp/CSharpTemp.h

@ -38,6 +38,7 @@ public: @@ -38,6 +38,7 @@ public:
const Bar& operator*(int m);
const Bar& operator++();
Bar operator++(int i);
void* arrayOfPrimitivePointers[1];
private:
int index;

Loading…
Cancel
Save