Skip to content

Commit 958536e

Browse files
committed
Exception handling for fields, too.
And handle the possibility that the NativeImplementation property is called on an invalid object (it will now return nullptr).
1 parent f20afd3 commit 958536e

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

Reinterop~/Fields.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ private static void GenerateSingleFieldAccessors(CppGenerationContext context, T
9090

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

93+
// Add a parameter in which to return the exception, if there is one.
94+
getParameters = getParameters.Concat(new[] { (ParameterName: "reinteropException", CallSiteName: "&reinteropException", Type: CppType.VoidPointerPointer, InteropType: CppType.VoidPointerPointer) });
95+
interopSetParameters = interopSetParameters + ", void** reinteropException";
96+
9397
var interopGetParameters = getParameters.Select(parameter => $"{parameter.InteropType.GetFullyQualifiedName()} {parameter.ParameterName}");
9498
var interopGetParametersCall = getParameters.Select(parameter => parameter.Type.GetConversionToInteropType(context, parameter.CallSiteName));
9599

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

146150
string[] invocation = new[]
147151
{
152+
$"void* reinteropException = nullptr;",
148153
$"auto result = Field_get_{field.Name}({string.Join(", ", interopGetParametersCall)});",
154+
$"if (reinteropException != nullptr) {{",
155+
$" throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));",
156+
$"}}",
149157
$"return {getType.GetConversionFromInteropType(context, "result")};"
150158
};
151159
if (hasStructRewrite)
@@ -154,17 +162,25 @@ private static void GenerateSingleFieldAccessors(CppGenerationContext context, T
154162
{
155163
invocation = new[]
156164
{
165+
$"void* reinteropException = nullptr;",
157166
$"{getType.GenericArguments.FirstOrDefault().GetFullyQualifiedName()} result;",
158167
$"std::uint8_t resultIsValid = Field_get_{field.Name}({string.Join(", ", interopGetParametersCall)});",
168+
$"if (reinteropException != nullptr) {{",
169+
$" throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));",
170+
$"}}",
159171
$"return resultIsValid ? std::make_optional(std::move({getType.GetConversionFromInteropType(context, "result")})) : std::nullopt;"
160172
};
161173
}
162174
else
163175
{
164176
invocation = new[]
165177
{
178+
$"void* reinteropException = nullptr;",
166179
$"{getType.GetFullyQualifiedName()} result;",
167180
$"Field_get_{field.Name}({string.Join(", ", interopGetParametersCall)});",
181+
$"if (reinteropException != nullptr) {{",
182+
$" throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));",
183+
$"}}",
168184
$"return {getType.GetConversionFromInteropType(context, "result")};"
169185
};
170186
}
@@ -181,22 +197,28 @@ private static void GenerateSingleFieldAccessors(CppGenerationContext context, T
181197
{
182198
definition.Type,
183199
getType,
184-
CppObjectHandle.GetCppType(context)
200+
CppObjectHandle.GetCppType(context),
201+
CppReinteropException.GetCppType(context)
185202
}
186203
));
187204

188205
definition.Elements.Add(new(
189206
Content:
190207
$$"""
191208
void {{definition.Type.Name}}::{{field.Name}}({{setType.GetFullyQualifiedName()}} value){{(field.IsStatic ? "" : " const")}} {
192-
Field_set_{{field.Name}}({{interopSetParametersCall}});
209+
void* reinteropException = nullptr;
210+
Field_set_{{field.Name}}({{interopSetParametersCall}}, &reinteropException);
211+
if (reinteropException != nullptr) {
212+
throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));
213+
}
193214
}
194215
""",
195216
TypeDefinitionsReferenced: new[]
196217
{
197218
definition.Type,
198219
setType,
199-
CppObjectHandle.GetCppType(context)
220+
CppObjectHandle.GetCppType(context),
221+
CppReinteropException.GetCppType(context)
200222
}
201223
));
202224
}

Reinterop~/Interop.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
7878
invocationTarget = $"{csType.GetFullyQualifiedName()}{accessName}";
7979
}
8080

81-
// Add a parameter in which to return the exception, if there is one.
82-
CSharpType exceptionCsType = CSharpType.FromSymbol(context, context.Compilation.GetSpecialType(SpecialType.System_IntPtr)).AsPointer();
83-
8481
CSharpType csReturnType = CSharpType.FromSymbol(context, returnType);
8582
CSharpType csInteropReturnType = csReturnType.AsInteropTypeReturn();
8683

@@ -102,6 +99,8 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
10299
});
103100
}
104101

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

107106
string interopReturnTypeString = csInteropReturnType.GetFullyQualifiedName();
@@ -257,7 +256,7 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
257256
{
258257
try
259258
{
260-
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
259+
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
261260
}
262261
catch (Exception e)
263262
{
@@ -328,6 +327,10 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
328327
});
329328
}
330329

330+
// Add a parameter in which to return the exception, if there is one.
331+
CSharpType exceptionCsType = CSharpType.FromSymbol(context, context.Compilation.GetSpecialType(SpecialType.System_IntPtr)).AsPointer();
332+
interopParameterDetails = interopParameterDetails.Concat(new[] { (Name: "reinteropException", Type: exceptionCsType, InteropType: exceptionCsType.AsInteropTypeParameter()) });
333+
331334
string interopReturnTypeString = csInteropReturnType.GetFullyQualifiedName();
332335
string callParameterList = string.Join(", ", callParameterDetails.Select(parameter => parameter.Type.GetParameterConversionFromInteropType(parameter.Name)));
333336
string interopParameterList = string.Join(", ", interopParameterDetails.Select(parameter => $"{parameter.InteropType.GetFullyQualifiedName()} {parameter.Name}"));
@@ -359,6 +362,20 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
359362

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

365+
string returnDefaultInstance = "";
366+
if (csInteropReturnType.SpecialType != SpecialType.System_Void)
367+
{
368+
if (csInteropReturnType.Symbol != null &&
369+
(csInteropReturnType.Symbol.TypeKind == TypeKind.Pointer || csInteropReturnType.Symbol.TypeKind == TypeKind.Class))
370+
{
371+
returnDefaultInstance = "return null;";
372+
}
373+
else
374+
{
375+
returnDefaultInstance = $$"""return new {{interopReturnTypeString}}();""";
376+
}
377+
}
378+
362379
return (
363380
Name: $"{baseName}Delegate",
364381
Content:
@@ -369,7 +386,15 @@ public static (string Name, string Content) CreateCSharpDelegateInit(
369386
[AOT.MonoPInvokeCallback(typeof({{baseName}}Type))]
370387
private static unsafe {{interopReturnTypeString}} {{baseName}}({{interopParameterList}})
371388
{
372-
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
389+
try
390+
{
391+
{{implementation.Replace(Environment.NewLine, Environment.NewLine + " ")}}
392+
}
393+
catch (Exception e)
394+
{
395+
*reinteropException = Reinterop.ObjectHandleUtility.CreateHandle(e);
396+
{{returnDefaultInstance}}
397+
}
373398
}
374399
"""
375400
);

Reinterop~/MethodsImplementedInCpp.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@ protected void DisposeImplementation()
208208
[AOT.MonoPInvokeCallback(typeof({{baseName}}Type))]
209209
private static unsafe System.IntPtr {{baseName}}(IntPtr thiz)
210210
{
211-
return ({{csWrapperType.GetParameterConversionFromInteropType("thiz")}}).NativeImplementation.DangerousGetHandle();
211+
var o = {{csWrapperType.GetParameterConversionFromInteropType("thiz")}};
212+
if (o == null)
213+
return System.IntPtr.Zero;
214+
return o.NativeImplementation.DangerousGetHandle();
212215
}
213216
"""
214217
));

0 commit comments

Comments
 (0)