Browse Source

Add marshalling for `std::optional` <=> `System::Nullable` (#1902)

pull/1909/head
Jelle 5 months ago committed by GitHub
parent
commit
33a9dea46d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 109
      src/Generator/Types/Std/Stdlib.CLI.cs

109
src/Generator/Types/Std/Stdlib.CLI.cs

@ -121,6 +121,110 @@ namespace CppSharp.Types.Std.CLI @@ -121,6 +121,110 @@ namespace CppSharp.Types.Std.CLI
ctx.ReturnVarName);
}
}
[TypeMap("std::optional", GeneratorKindID = GeneratorKind.CLI_ID)]
public class Optional : TypeMap
{
public override bool IsIgnored
{
get
{
var finalType = Type.GetFinalPointee() ?? Type;
if (finalType is not TemplateSpecializationType type)
{
var injectedClassNameType = (InjectedClassNameType)finalType;
type = (TemplateSpecializationType)injectedClassNameType.InjectedSpecializationType.Type;
}
var checker = new TypeIgnoreChecker(TypeMapDatabase);
type.Arguments[0].Type.Visit(checker);
return checker.IsIgnored;
}
}
public override Type SignatureType(TypePrinterContext ctx)
{
return new CustomType($"System::Nullable<{ ctx.GetTemplateParameterList() }>");
}
public override void MarshalToNative(MarshalContext ctx)
{
var desugared = Type.Desugar();
var templateType = desugared as TemplateSpecializationType;
var type = templateType!.Arguments[0].Type;
var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType();
var managedType = isPointerToPrimitive
? new CILType(typeof(nint))
: type.Type;
var paramName = ctx.Parameter?.Name ?? ctx.ArgName;
ctx.Before.WriteLineIndent("if (!{0}.HasValue)", paramName);
ctx.Before.WriteOpenBraceAndIndent();
{
ctx.Before.WriteLine("{0} = std::nullopt;", ctx.ReturnVarName);
ctx.Before.WriteLine("return;");
ctx.Before.UnindentAndWriteCloseBrace();
}
var param = new Parameter
{
Name = paramName + ".Value",
QualifiedType = type
};
var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation)
{
Parameter = param,
ArgName = param.Name,
};
var marshal = new CLIMarshalManagedToNativePrinter(elementCtx);
type.Type.Visit(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
ctx.Before.Write(marshal.Context.Before);
if (isPointerToPrimitive)
ctx.Return.Write("{0}.ToPointer()", marshal.Context.Return);
else
ctx.Return.Write(marshal.Context.Return);
}
public override void MarshalToManaged(MarshalContext ctx)
{
var desugared = Type.Desugar();
var templateType = desugared as TemplateSpecializationType;
var type = templateType!.Arguments[0].Type;
var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType();
var managedType = isPointerToPrimitive
? new CILType(typeof(nint))
: type.Type;
ctx.Before.WriteLineIndent("if (!{0}.has_value())", ctx.ArgName);
{
ctx.Before.WriteLine("return {};");
ctx.Before.Unindent();
}
var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation)
{
ReturnVarName = ctx.ReturnVarName + ".value()",
ReturnType = type
};
var marshal = new CLIMarshalNativeToManagedPrinter(elementCtx);
type.Type.Visit(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
ctx.Before.Write(marshal.Context.Before);
if (isPointerToPrimitive)
ctx.Return.Write("{0}({1})", managedType, marshal.Context.Return);
else
ctx.Return.Write(marshal.Context.Return);
}
}
[TypeMap("std::vector", GeneratorKindID = GeneratorKind.CLI_ID)]
public class Vector : TypeMap
@ -159,8 +263,7 @@ namespace CppSharp.Types.Std.CLI @@ -159,8 +263,7 @@ namespace CppSharp.Types.Std.CLI
? new CILType(typeof(System.IntPtr))
: type.Type;
var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name
: ctx.ArgName;
var entryString = ctx.Parameter?.Name ?? ctx.ArgName;
var tmpVarName = "_tmp" + entryString;
@ -314,7 +417,7 @@ namespace CppSharp.Types.Std.CLI @@ -314,7 +417,7 @@ namespace CppSharp.Types.Std.CLI
[TypeMap("std::nullptr_t", GeneratorKindID = GeneratorKind.CLI_ID)]
public class NullPtr : TypeMap
{
public override bool DoesMarshalling { get { return false; } }
public override bool DoesMarshalling => false;
public override void CLITypeReference(CLITypeReferenceCollector collector,
ASTRecord<Declaration> loc)

Loading…
Cancel
Save