Skip to content

Commit

Permalink
Exception handling for fields, too.
Browse files Browse the repository at this point in the history
And handle the possibility that the NativeImplementation property is
called on an invalid object (it will now return nullptr).
  • Loading branch information
kring committed Jan 28, 2025
1 parent f20afd3 commit 958536e
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
28 changes: 25 additions & 3 deletions Reinterop~/Fields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ private static void GenerateSingleFieldAccessors(CppGenerationContext context, T

bool hasStructRewrite = Interop.RewriteStructReturn(ref getParameters, ref getType, ref getInteropType);

// Add a parameter in which to return the exception, if there is one.
getParameters = getParameters.Concat(new[] { (ParameterName: "reinteropException", CallSiteName: "&reinteropException", Type: CppType.VoidPointerPointer, InteropType: CppType.VoidPointerPointer) });
interopSetParameters = interopSetParameters + ", void** reinteropException";

var interopGetParameters = getParameters.Select(parameter => $"{parameter.InteropType.GetFullyQualifiedName()} {parameter.ParameterName}");
var interopGetParametersCall = getParameters.Select(parameter => parameter.Type.GetConversionToInteropType(context, parameter.CallSiteName));

Expand Down Expand Up @@ -145,7 +149,11 @@ private static void GenerateSingleFieldAccessors(CppGenerationContext context, T

string[] invocation = new[]
{
$"void* reinteropException = nullptr;",
$"auto result = Field_get_{field.Name}({string.Join(", ", interopGetParametersCall)});",
$"if (reinteropException != nullptr) {{",
$" throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));",
$"}}",
$"return {getType.GetConversionFromInteropType(context, "result")};"
};
if (hasStructRewrite)
Expand All @@ -154,17 +162,25 @@ private static void GenerateSingleFieldAccessors(CppGenerationContext context, T
{
invocation = new[]
{
$"void* reinteropException = nullptr;",
$"{getType.GenericArguments.FirstOrDefault().GetFullyQualifiedName()} result;",
$"std::uint8_t resultIsValid = Field_get_{field.Name}({string.Join(", ", interopGetParametersCall)});",
$"if (reinteropException != nullptr) {{",
$" throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));",
$"}}",
$"return resultIsValid ? std::make_optional(std::move({getType.GetConversionFromInteropType(context, "result")})) : std::nullopt;"
};
}
else
{
invocation = new[]
{
$"void* reinteropException = nullptr;",
$"{getType.GetFullyQualifiedName()} result;",
$"Field_get_{field.Name}({string.Join(", ", interopGetParametersCall)});",
$"if (reinteropException != nullptr) {{",
$" throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));",
$"}}",
$"return {getType.GetConversionFromInteropType(context, "result")};"
};
}
Expand All @@ -181,22 +197,28 @@ private static void GenerateSingleFieldAccessors(CppGenerationContext context, T
{
definition.Type,
getType,
CppObjectHandle.GetCppType(context)
CppObjectHandle.GetCppType(context),
CppReinteropException.GetCppType(context)
}
));

definition.Elements.Add(new(
Content:
$$"""
void {{definition.Type.Name}}::{{field.Name}}({{setType.GetFullyQualifiedName()}} value){{(field.IsStatic ? "" : " const")}} {
Field_set_{{field.Name}}({{interopSetParametersCall}});
void* reinteropException = nullptr;
Field_set_{{field.Name}}({{interopSetParametersCall}}, &reinteropException);
if (reinteropException != nullptr) {
throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));
}
}
""",
TypeDefinitionsReferenced: new[]
{
definition.Type,
setType,
CppObjectHandle.GetCppType(context)
CppObjectHandle.GetCppType(context),
CppReinteropException.GetCppType(context)
}
));
}
Expand Down
35 changes: 30 additions & 5 deletions Reinterop~/Interop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
invocationTarget = $"{csType.GetFullyQualifiedName()}{accessName}";
}

// Add a parameter in which to return the exception, if there is one.
CSharpType exceptionCsType = CSharpType.FromSymbol(context, context.Compilation.GetSpecialType(SpecialType.System_IntPtr)).AsPointer();

CSharpType csReturnType = CSharpType.FromSymbol(context, returnType);
CSharpType csInteropReturnType = csReturnType.AsInteropTypeReturn();

Expand All @@ -102,6 +99,8 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
});
}

// Add a parameter in which to return the exception, if there is one.
CSharpType exceptionCsType = CSharpType.FromSymbol(context, context.Compilation.GetSpecialType(SpecialType.System_IntPtr)).AsPointer();
interopParameterDetails = interopParameterDetails.Concat(new[] { (Name: "reinteropException", Type: exceptionCsType, InteropType: exceptionCsType.AsInteropTypeParameter()) });

string interopReturnTypeString = csInteropReturnType.GetFullyQualifiedName();
Expand Down Expand Up @@ -257,7 +256,7 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
{
try
{
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
}
catch (Exception e)
{
Expand Down Expand Up @@ -328,6 +327,10 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
});
}

// Add a parameter in which to return the exception, if there is one.
CSharpType exceptionCsType = CSharpType.FromSymbol(context, context.Compilation.GetSpecialType(SpecialType.System_IntPtr)).AsPointer();
interopParameterDetails = interopParameterDetails.Concat(new[] { (Name: "reinteropException", Type: exceptionCsType, InteropType: exceptionCsType.AsInteropTypeParameter()) });

string interopReturnTypeString = csInteropReturnType.GetFullyQualifiedName();
string callParameterList = string.Join(", ", callParameterDetails.Select(parameter => parameter.Type.GetParameterConversionFromInteropType(parameter.Name)));
string interopParameterList = string.Join(", ", interopParameterDetails.Select(parameter => $"{parameter.InteropType.GetFullyQualifiedName()} {parameter.Name}"));
Expand Down Expand Up @@ -359,6 +362,20 @@ public static (string Name, string Content) CreateCSharpDelegateInit(

string baseName = $"{GetUniqueNameForType(csType)}_Field_{(isGet ? "get" : "set")}_{field.Name}";

string returnDefaultInstance = "";
if (csInteropReturnType.SpecialType != SpecialType.System_Void)
{
if (csInteropReturnType.Symbol != null &&
(csInteropReturnType.Symbol.TypeKind == TypeKind.Pointer || csInteropReturnType.Symbol.TypeKind == TypeKind.Class))
{
returnDefaultInstance = "return null;";
}
else
{
returnDefaultInstance = $$"""return new {{interopReturnTypeString}}();""";
}
}

return (
Name: $"{baseName}Delegate",
Content:
Expand All @@ -369,7 +386,15 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
[AOT.MonoPInvokeCallback(typeof({{baseName}}Type))]
private static unsafe {{interopReturnTypeString}} {{baseName}}({{interopParameterList}})
{
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
try
{
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
}
catch (Exception e)
{
*reinteropException = Reinterop.ObjectHandleUtility.CreateHandle(e);
{{returnDefaultInstance}}
}
}
"""
);
Expand Down
5 changes: 4 additions & 1 deletion Reinterop~/MethodsImplementedInCpp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,10 @@ protected void DisposeImplementation()
[AOT.MonoPInvokeCallback(typeof({{baseName}}Type))]
private static unsafe System.IntPtr {{baseName}}(IntPtr thiz)
{
return ({{csWrapperType.GetParameterConversionFromInteropType("thiz")}}).NativeImplementation.DangerousGetHandle();
var o = {{csWrapperType.GetParameterConversionFromInteropType("thiz")}};
if (o == null)
return System.IntPtr.Zero;
return o.NativeImplementation.DangerousGetHandle();
}
"""
));
Expand Down

0 comments on commit 958536e

Please sign in to comment.