@@ -42,8 +42,14 @@ public static void GenerateSingleMethod(CppGenerationContext context, TypeToGene
4242
4343 string interopName = $ "Call{ method . Name } _{ Interop . HashParameters ( method . Parameters , method . TypeArguments ) } ";
4444
45+ // If this is an instance method, pass the current object as the first (implicit "thiz") parameter.
46+ CppType ? instanceType = method . IsStatic ? null : result . CppDefinition . Type . AsParameterType ( ) ;
47+ CppInteropFunction recipe = new CppInteropFunction ( context , interopName , parameters , returnType , instanceType ) ;
48+
4549 // For op_Equality/op_Inequality, the interop function itself is private, and a public operator==/!= is added below to call it.
4650 bool addOperator = method . MethodKind == MethodKind . UserDefinedOperator && ( method . Name == "op_Equality" || method . Name == "op_Inequality" ) ;
51+ if ( addOperator )
52+ recipe . AsPrivate ( ) ;
4753
4854 if ( method . IsGenericMethod )
4955 {
@@ -68,82 +74,14 @@ public static void GenerateSingleMethod(CppGenerationContext context, TypeToGene
6874 ) ) ;
6975 }
7076
71- // Parameters of generic type are always passed as const references for maximum compatibility
72- Debug . Assert ( parameters . Length == genericMethod . Parameters . Length ) ;
73- for ( int i = 0 ; i < parameters . Length && i < genericMethod . Parameters . Length ; ++ i )
74- {
75- IParameterSymbol genericParameter = genericMethod . Parameters [ i ] ;
76- CppInteropParameter parameter = parameters [ i ] ;
77-
78- if ( genericParameter . Type . TypeKind == TypeKind . TypeParameter && ( ! parameter . Type . Flags . HasFlag ( CppTypeFlags . Reference ) || ! parameter . Type . Flags . HasFlag ( CppTypeFlags . Const ) ) )
79- {
80- parameters [ i ] = parameter with { Type = parameter . Type . AsConstReference ( ) } ;
81- }
82- }
83- }
84-
85- // If this is an instance method, pass the current object as the first (implicit "thiz") parameter.
86- CppType ? instanceType = method . IsStatic ? null : result . CppDefinition . Type . AsParameterType ( ) ;
87- CppInteropFunction recipe = new CppInteropFunction ( context , interopName , parameters , returnType , instanceType ) ;
88-
89- if ( addOperator )
90- recipe . AsPrivate ( ) ;
91-
92- if ( method . IsGenericMethod )
93- {
9477 // The generic template's own declaration was added above; only its specialization's definition is needed here.
9578 recipe . WithoutDeclaration ( ) . AsTemplateSpecialization ( method . TypeArguments . Select ( t => CppType . FromCSharp ( context , t ) ) ) ;
9679 }
9780
9881 // A private, static field of function pointer type that will call into a managed delegate
9982 // for this method, initialized at startup, plus the method's own declaration and definition.
10083 var ( csName , csContent ) = Interop . CreateCSharpDelegateInit ( context , item . Type , method , interopName ) ;
101- IReadOnlyList < CppStatement > ? body = recipe . Body ( ) ;
102- recipe . AddToGeneration ( result , method . Name , csName , csContent , body ) ;
103-
104- if ( body == null )
105- {
106- // The Nullable-with-struct-rewrite case (returns a "resultIsValid" flag alongside an
107- // out-parameter) isn't modeled by CppInteropFunction.Body, so it's still built as a
108- // plain string template.
109- var parameterPassStrings = recipe . InteropParameters . Select ( parameter => parameter . Type . GetConversionToInteropType ( context , parameter . CallSiteName ) ) ;
110- parameterPassStrings = parameterPassStrings . Concat ( new [ ] { "&reinteropException" } ) . Where ( s => ! string . IsNullOrEmpty ( s ) ) ;
111-
112- string [ ] invocation = new [ ]
113- {
114- $ "{ returnType . GenericArguments . FirstOrDefault ( ) . GetFullyQualifiedName ( ) } result;",
115- $ "std::uint8_t resultIsValid = { interopName } ({ string . Join ( ", " , parameterPassStrings ) } );"
116- } ;
117- string returnStatement = $ "return resultIsValid ? std::make_optional(std::move({ returnType . GetConversionFromInteropType ( context , "result" ) } )) : std::nullopt;";
118-
119- string modifiers = method . IsStatic ? "static " : "" ;
120- string afterModifiers = method . IsStatic ? "" : " const" ;
121- string templatePrefix = method . IsGenericMethod ? "template <> " : "" ;
122- string templateSpecialization = method . IsGenericMethod
123- ? $ "<{ string . Join ( ", " , method . TypeArguments . Select ( t => CppType . FromCSharp ( context , t ) . GetFullyQualifiedName ( ) ) ) } >"
124- : "" ;
125- string typeTemplateSpecialization = CppInteropFunction . GetTypeTemplateSpecialization ( definition . Type ) ;
126-
127- definition . Elements . Add ( new (
128- Content :
129- $$ """
130- {{ templatePrefix }} {{ returnType . GetFullyQualifiedName ( ) }} {{ definition . Type . Name }} {{ typeTemplateSpecialization }} ::{{ method . Name }} {{ templateSpecialization }} ({{ recipe . ParameterListDeclaration ( ) }} ){{ afterModifiers }} {
131- void* reinteropException = nullptr;
132- {{ GenerationUtility . JoinAndIndent ( invocation , " " ) }}
133- if (reinteropException != nullptr)
134- throw Reinterop::ReinteropNativeException(::DotNet::System::Exception(::DotNet::Reinterop::ObjectHandle(reinteropException)));
135- {{ returnStatement }}
136- }
137- """ ,
138- TypeDefinitionsReferenced : new [ ]
139- {
140- definition . Type ,
141- returnType ,
142- CppObjectHandle . GetCppType ( context ) ,
143- CppReinteropException . GetCppType ( context )
144- } . Concat ( recipe . ParameterTypes )
145- ) ) ;
146- }
84+ recipe . AddToGeneration ( result , method . Name , csName , csContent , recipe . Body ( ) ) ;
14785
14886 if ( addOperator )
14987 {
0 commit comments