Skip to content

Commit 33a9dea

Browse files
authored
Add marshalling for std::optional <=> System::Nullable (#1902)
1 parent 18d817f commit 33a9dea

File tree

1 file changed

+106
-3
lines changed

1 file changed

+106
-3
lines changed

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

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,110 @@ public override void MarshalToManaged(MarshalContext ctx)
121121
ctx.ReturnVarName);
122122
}
123123
}
124+
125+
[TypeMap("std::optional", GeneratorKindID = GeneratorKind.CLI_ID)]
126+
public class Optional : TypeMap
127+
{
128+
public override bool IsIgnored
129+
{
130+
get
131+
{
132+
var finalType = Type.GetFinalPointee() ?? Type;
133+
if (finalType is not TemplateSpecializationType type)
134+
{
135+
var injectedClassNameType = (InjectedClassNameType)finalType;
136+
type = (TemplateSpecializationType)injectedClassNameType.InjectedSpecializationType.Type;
137+
}
138+
var checker = new TypeIgnoreChecker(TypeMapDatabase);
139+
type.Arguments[0].Type.Visit(checker);
140+
141+
return checker.IsIgnored;
142+
}
143+
}
144+
145+
public override Type SignatureType(TypePrinterContext ctx)
146+
{
147+
return new CustomType($"System::Nullable<{ ctx.GetTemplateParameterList() }>");
148+
}
149+
150+
public override void MarshalToNative(MarshalContext ctx)
151+
{
152+
var desugared = Type.Desugar();
153+
var templateType = desugared as TemplateSpecializationType;
154+
var type = templateType!.Arguments[0].Type;
155+
var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType();
156+
var managedType = isPointerToPrimitive
157+
? new CILType(typeof(nint))
158+
: type.Type;
159+
160+
var paramName = ctx.Parameter?.Name ?? ctx.ArgName;
161+
162+
ctx.Before.WriteLineIndent("if (!{0}.HasValue)", paramName);
163+
ctx.Before.WriteOpenBraceAndIndent();
164+
{
165+
ctx.Before.WriteLine("{0} = std::nullopt;", ctx.ReturnVarName);
166+
ctx.Before.WriteLine("return;");
167+
ctx.Before.UnindentAndWriteCloseBrace();
168+
}
169+
170+
var param = new Parameter
171+
{
172+
Name = paramName + ".Value",
173+
QualifiedType = type
174+
};
175+
176+
var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation)
177+
{
178+
Parameter = param,
179+
ArgName = param.Name,
180+
};
181+
182+
var marshal = new CLIMarshalManagedToNativePrinter(elementCtx);
183+
type.Type.Visit(marshal);
184+
185+
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
186+
ctx.Before.Write(marshal.Context.Before);
187+
188+
if (isPointerToPrimitive)
189+
ctx.Return.Write("{0}.ToPointer()", marshal.Context.Return);
190+
else
191+
ctx.Return.Write(marshal.Context.Return);
192+
}
193+
194+
public override void MarshalToManaged(MarshalContext ctx)
195+
{
196+
var desugared = Type.Desugar();
197+
var templateType = desugared as TemplateSpecializationType;
198+
var type = templateType!.Arguments[0].Type;
199+
var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType();
200+
var managedType = isPointerToPrimitive
201+
? new CILType(typeof(nint))
202+
: type.Type;
203+
204+
ctx.Before.WriteLineIndent("if (!{0}.has_value())", ctx.ArgName);
205+
{
206+
ctx.Before.WriteLine("return {};");
207+
ctx.Before.Unindent();
208+
}
209+
210+
var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation)
211+
{
212+
ReturnVarName = ctx.ReturnVarName + ".value()",
213+
ReturnType = type
214+
};
215+
216+
var marshal = new CLIMarshalNativeToManagedPrinter(elementCtx);
217+
type.Type.Visit(marshal);
218+
219+
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
220+
ctx.Before.Write(marshal.Context.Before);
221+
222+
if (isPointerToPrimitive)
223+
ctx.Return.Write("{0}({1})", managedType, marshal.Context.Return);
224+
else
225+
ctx.Return.Write(marshal.Context.Return);
226+
}
227+
}
124228

125229
[TypeMap("std::vector", GeneratorKindID = GeneratorKind.CLI_ID)]
126230
public class Vector : TypeMap
@@ -159,8 +263,7 @@ public override void MarshalToNative(MarshalContext ctx)
159263
? new CILType(typeof(System.IntPtr))
160264
: type.Type;
161265

162-
var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name
163-
: ctx.ArgName;
266+
var entryString = ctx.Parameter?.Name ?? ctx.ArgName;
164267

165268
var tmpVarName = "_tmp" + entryString;
166269

@@ -314,7 +417,7 @@ public override void MarshalToNative(MarshalContext ctx)
314417
[TypeMap("std::nullptr_t", GeneratorKindID = GeneratorKind.CLI_ID)]
315418
public class NullPtr : TypeMap
316419
{
317-
public override bool DoesMarshalling { get { return false; } }
420+
public override bool DoesMarshalling => false;
318421

319422
public override void CLITypeReference(CLITypeReferenceCollector collector,
320423
ASTRecord<Declaration> loc)

0 commit comments

Comments
 (0)