in SharpGen/Generator/ReverseCallablePrologCodeGenerator.cs [110:230]
private IEnumerable<StatementSyntax> GenerateNativeByRefProlog(CsMarshalCallableBase publicElement,
ExpressionSyntax nativeParameter,
TypeSyntax nativeParameterType)
{
var marshaller = GetMarshaller(publicElement);
var marshalTypeSyntax = marshaller.GetMarshalTypeSyntax(publicElement);
var publicType = ParseTypeName(publicElement.PublicType.QualifiedName);
var generatesMarshalVariable = marshaller.GeneratesMarshalVariable(publicElement);
ExpressionSyntax publicDefaultValue = publicElement.UsedAsReturn ? default : DefaultLiteral;
var refToNativeClause = GenerateAsRefInitializer(publicElement, nativeParameter, marshalTypeSyntax);
TypeSyntax publicVariableType, marshalVariableType;
ExpressionSyntax publicVariableInitializer, marshalVariableInitializer;
if (publicElement is CsParameter {IsOptional: true, IsLocalManagedReference: true} parameter)
{
Debug.Assert(marshaller is RefWrapperMarshaller);
var refVariableDeclaration = LocalDeclarationStatement(
VariableDeclaration(
RefType(marshalTypeSyntax),
SingletonSeparatedList(
VariableDeclarator(
MarshallerBase.GetRefLocationIdentifier(publicElement),
default, EqualsValueClause(refToNativeClause)
)
)
)
);
publicVariableType = publicType;
marshalVariableType = marshalTypeSyntax;
publicVariableInitializer = publicDefaultValue;
marshalVariableInitializer = DefaultLiteral;
if (generatesMarshalVariable && parameter is {IsRef: true})
{
Logger.Error(
null, "Optional ref parameter [{0}] that requires generating marshal variable is unsupported.",
parameter.QualifiedName
);
}
else
{
Debug.Assert(!generatesMarshalVariable || parameter is {IsOut: true});
}
yield return refVariableDeclaration;
}
else
{
Debug.Assert(marshaller is not RefWrapperMarshaller);
marshalVariableInitializer = refToNativeClause;
if (publicElement is {IsLocalManagedReference: true})
{
Debug.Assert(publicElement is CsReturnValue or CsParameter {IsOptional: false});
marshalVariableType = RefType(marshalTypeSyntax);
publicVariableType = generatesMarshalVariable
? publicType
: RefType(publicType);
publicVariableInitializer = generatesMarshalVariable
? publicDefaultValue
: refToNativeClause;
}
else
{
Debug.Assert(publicElement is CsParameter {IsRefIn: true});
var isNullable = publicElement is CsParameter {PassedByNullableInstance: true};
marshalVariableType = marshalTypeSyntax;
publicVariableType = isNullable ? NullableType(publicType) : publicType;
publicVariableInitializer = generatesMarshalVariable
? isNullable
? ConditionalExpression(
BinaryExpression(
SyntaxKind.NotEqualsExpression,
nativeParameter, DefaultLiteral
),
ImplicitObjectCreationExpression(),
LiteralExpression(SyntaxKind.NullLiteralExpression)
)
: publicDefaultValue
: refToNativeClause;
}
}
if (generatesMarshalVariable)
{
yield return LocalDeclarationStatement(
VariableDeclaration(
marshalVariableType,
SingletonSeparatedList(
VariableDeclarator(
MarshallerBase.GetMarshalStorageLocationIdentifier(publicElement),
default, EqualsValueClause(marshalVariableInitializer)
)
)
)
);
}
yield return LocalDeclarationStatement(
VariableDeclaration(
publicVariableType,
SingletonSeparatedList(
VariableDeclarator(
Identifier(publicElement.Name), default,
publicVariableInitializer != default
? EqualsValueClause(publicVariableInitializer)
: default
)
)
)
);
}