[.NET] Prefer spans of handles over plain ints where possible

Uses the P/Invoke source generation in conjunction with the custom CanteraHandler marshaller, to marshal arrays, not just scalars, of the typed handle classes.
This commit is contained in:
Sammo Gabay
2025-06-17 07:20:41 -06:00
committed by Ingmar Schoegl
parent 539b6f2872
commit 40b489c160
3 changed files with 20 additions and 5 deletions
@@ -46,10 +46,8 @@ abstract class CanteraHandle : IDisposable
public sealed override string ToString() =>
$"{GetType().Name} {{{_value}}}";
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder), MarshalMode.ManagedToUnmanagedIn,
typeof(Marshaller<>))]
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder), MarshalMode.ManagedToUnmanagedOut,
typeof(Marshaller<>))]
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder),
MarshalMode.Default, typeof(Marshaller<>))]
public static class Marshaller<T> where T : CanteraHandle, new()
{
public static int ConvertToUnmanaged(T handle)
@@ -68,6 +68,12 @@ class_accessors:
kin_parent: SolutionHandle
trans_parent: SolutionHandle
# Functions that are typed to take an array of ints, but are really
# supposed to take an array of handles
handle_array_takers:
sol_newInterface: SolutionHandle
reactornet_new: ReactorHandle
# Handles for which there is no special delete function,
# so we need to generate them manually because we can't
# discover the type name from the delete.
@@ -33,6 +33,8 @@ class Config:
class_accessors: dict[str, str]
handle_array_takers: dict[str, str]
derived_handles: dict[str, str]
wrapper_classes: dict[str, dict[str, str]]
@@ -172,8 +174,17 @@ class CSharpSourceGenerator(SourceGenerator):
ret_type = crosswalk(ret_type)
handle_array_type = self._config.handle_array_takers.get(name)
for i, param in enumerate(params):
param_type = crosswalk(param.p_type)
if handle_array_type and param_type.endswith("Span<int>"):
# There is a slight inconsistency in CLib in that sometimes
# the collection of handles will be marked as const and sometimes not.
# However, is it never modified, so we can always use a ReadOnlySpan.
# When this inconsistency is removed, the above can become
# param_type == "ReadOnlySpan<int>"
param_type = f"ReadOnlySpan<{handle_array_type}>"
params[i] = Param(param_type, param.name, param.description,
param.direction, param.default, param.base)
@@ -225,7 +236,7 @@ class CSharpSourceGenerator(SourceGenerator):
span_param_name=func.arglist[-1].name)
for func in cs_funcs if func.gets_string())
# Add wrappers for functions that get or set arrays of doubles.
# Add wrappers for functions that get or set arrays.
def transform_to_span_func(func: CsFunc) -> CsFunc:
arglist = ArgList([*func.arglist[:-2], func.arglist[-1]])
return CsFunc('void', func.name, arglist, False, None)