Browse Source

Copy arrays of primitive values using System.Buffers.MemoryCopy (#1440)

pull/1445/head
josetr 5 years ago committed by GitHub
parent
commit
133a1882df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/AST/TypeExtensions.cs
  2. 74
      src/Generator/Generators/CSharp/CSharpMarshal.cs

5
src/AST/TypeExtensions.cs

@ -435,5 +435,10 @@
return declaration.TranslationUnit.Module; return declaration.TranslationUnit.Module;
} }
public static long GetSizeInBytes(this ArrayType array)
{
return array.Size * (array.ElementSize / 8);
}
} }
} }

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

@ -80,38 +80,50 @@ namespace CppSharp.Generators.CSharp
supportBefore.WriteLine($"if ({Context.ReturnVarName} != null)"); supportBefore.WriteLine($"if ({Context.ReturnVarName} != null)");
supportBefore.WriteOpenBraceAndIndent(); supportBefore.WriteOpenBraceAndIndent();
supportBefore.WriteLine($"{value} = new {arrayType}[{array.Size}];"); supportBefore.WriteLine($"{value} = new {arrayType}[{array.Size}];");
supportBefore.WriteLine($"for (int i = 0; i < {array.Size}; i++)");
if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void)) if (CheckIfArrayCanBeCopiedUsingMemoryCopy(array))
supportBefore.WriteLineIndent($@"{value}[i] = new global::System.IntPtr({
Context.ReturnVarName}[i]);");
else
{ {
var finalArrayType = arrayType.GetPointee() ?? arrayType; var arraySizeInBytes = array.GetSizeInBytes();
Class @class; var fixedArray = Generator.GeneratedIdentifier($"{value}fixed");
if ((finalArrayType.TryGetClass(out @class)) && @class.IsRefType) supportBefore.WriteLine($"fixed (void* {fixedArray} = {value})");
{ supportBefore.WriteLineIndent(
if (arrayType == finalArrayType) $"System.Buffer.MemoryCopy((void*){Context.ReturnVarName}, {fixedArray}, {arraySizeInBytes}, {arraySizeInBytes});");
supportBefore.WriteLineIndent( }
"{0}[i] = {1}.{2}(*(({1}.{3}*)&({4}[i * sizeof({1}.{3})])));", else {
value, array.Type, Helpers.CreateInstanceIdentifier, supportBefore.WriteLine($"for (int i = 0; i < {array.Size}; i++)");
Helpers.InternalStruct, Context.ReturnVarName); if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void))
else supportBefore.WriteLineIndent($@"{value}[i] = new global::System.IntPtr({
supportBefore.WriteLineIndent( Context.ReturnVarName}[i]);");
$@"{value}[i] = {finalArrayType}.{Helpers.CreateInstanceIdentifier}(({
typePrinter.IntPtrType}) {Context.ReturnVarName}[i]);");
}
else else
{ {
if (arrayType.IsPrimitiveType(PrimitiveType.Bool) && Context.MarshalKind == MarshalKind.NativeField)
supportBefore.WriteLineIndent($@"{value}[i] = { var finalArrayType = arrayType.GetPointee() ?? arrayType;
Context.ReturnVarName}[i] != 0;"); Class @class;
else if (arrayType.IsPrimitiveType(PrimitiveType.Char) && if ((finalArrayType.TryGetClass(out @class)) && @class.IsRefType)
Context.Context.Options.MarshalCharAsManagedChar) {
supportBefore.WriteLineIndent($@"{value}[i] = global::System.Convert.ToChar({ if (arrayType == finalArrayType)
Context.ReturnVarName}[i]);"); supportBefore.WriteLineIndent(
"{0}[i] = {1}.{2}(*(({1}.{3}*)&({4}[i * sizeof({1}.{3})])));",
value, array.Type, Helpers.CreateInstanceIdentifier,
Helpers.InternalStruct, Context.ReturnVarName);
else
supportBefore.WriteLineIndent(
$@"{value}[i] = {finalArrayType}.{Helpers.CreateInstanceIdentifier}(({
typePrinter.IntPtrType}) {Context.ReturnVarName}[i]);");
}
else else
supportBefore.WriteLineIndent($@"{value}[i] = { {
Context.ReturnVarName}[i];"); if (arrayType.IsPrimitiveType(PrimitiveType.Bool) && Context.MarshalKind == MarshalKind.NativeField)
supportBefore.WriteLineIndent($@"{value}[i] = {
Context.ReturnVarName}[i] != 0;");
else if (arrayType.IsPrimitiveType(PrimitiveType.Char) &&
Context.Context.Options.MarshalCharAsManagedChar)
supportBefore.WriteLineIndent($@"{value}[i] = global::System.Convert.ToChar({
Context.ReturnVarName}[i]);");
else
supportBefore.WriteLineIndent($@"{value}[i] = {
Context.ReturnVarName}[i];");
}
} }
} }
supportBefore.UnindentAndWriteCloseBrace(); supportBefore.UnindentAndWriteCloseBrace();
@ -428,6 +440,12 @@ namespace CppSharp.Generators.CSharp
Context.Return.Write(intermediateArray); Context.Return.Write(intermediateArray);
} }
public bool CheckIfArrayCanBeCopiedUsingMemoryCopy(ArrayType array)
{
return array.Type.IsPrimitiveType(out var primitive) &&
(!Context.Context.Options.MarshalCharAsManagedChar || primitive != PrimitiveType.Char);
}
private readonly CSharpTypePrinter typePrinter; private readonly CSharpTypePrinter typePrinter;
} }

Loading…
Cancel
Save