@@ -72,7 +72,7 @@ private void GenerateDelegate(CppGenerationContext context, GeneratedResult resu
7272 """
7373 ) ) ;
7474
75- // A a C# delegate type that wraps a std::function, and arrange for
75+ // A C# delegate type that wraps a std::function, and arranges for
7676 // the invoke and dispose to be implemented in C++.
7777 CSharpType csType = CSharpType . FromSymbol ( context , item . Type ) ;
7878
@@ -88,7 +88,7 @@ private void GenerateDelegate(CppGenerationContext context, GeneratedResult resu
8888 string disposeCallbackName = $ "{ csType . GetFullyQualifiedNamespace ( ) . Replace ( "." , "_" ) } _{ item . Type . Name } { genericTypeHash } _DisposeCallback";
8989
9090 var invokeParameters = callbackParameters . Select ( p => $ "{ p . CsType . GetFullyQualifiedName ( ) } { p . Name } ") ;
91- var invokeInteropParameters = new [ ] { "IntPtr callbackFunction" } . Concat ( callbackParameters . Select ( p => $ "{ p . CsType . AsInteropTypeParameter ( ) . GetFullyQualifiedName ( ) } { p . Name } ") ) ;
91+ var invokeInteropParameters = new [ ] { "ImplementationHandle callbackFunction" } . Concat ( callbackParameters . Select ( p => $ "{ p . CsType . AsInteropTypeParameter ( ) . GetFullyQualifiedName ( ) } { p . Name } ") ) ;
9292 var callInvokeInteropParameters = new [ ] { "_callbackFunction" } . Concat ( callbackParameters . Select ( p => p . CsType . GetConversionToInteropType ( p . Name ) ) ) ;
9393 var csReturnType = CSharpType . FromSymbol ( context , invokeMethod . ReturnType ) ;
9494
@@ -109,46 +109,57 @@ private void GenerateDelegate(CppGenerationContext context, GeneratedResult resu
109109 $$ """
110110 private class {{ csType . Name }} {{ genericTypeHash }} NativeFunction : System.IDisposable
111111 {
112- private IntPtr _callbackFunction;
113-
114- public {{ csType . Name }} {{ genericTypeHash }} NativeFunction(IntPtr callbackFunction)
112+ internal class ImplementationHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
115113 {
116- _callbackFunction = callbackFunction;
117- }
114+ public ImplementationHandle(IntPtr nativeImplementation) : base(true)
115+ {
116+ SetHandle(nativeImplementation);
117+ }
118118
119- ~{{ csType . Name }} {{ genericTypeHash }} NativeFunction()
120- {
121- Dispose(false);
119+ [System.Runtime.ConstrainedExecution.ReliabilityContract(System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState, System.Runtime.ConstrainedExecution.Cer.Success)]
120+ protected override bool ReleaseHandle()
121+ {
122+ {{ disposeCallbackName }} (this.handle);
123+ return true;
124+ }
122125 }
123-
124- public void Dispose()
126+
127+ [System.NonSerialized]
128+ private ImplementationHandle _callbackFunction;
129+
130+ public {{ csType . Name }} {{ genericTypeHash }} NativeFunction(IntPtr callbackFunction)
125131 {
126- Dispose(true);
127- GC.SuppressFinalize(this);
132+ _callbackFunction = new ImplementationHandle(callbackFunction);
128133 }
129134
130- private void Dispose(bool disposing )
135+ public void Dispose()
131136 {
132- if (_callbackFunction != IntPtr.Zero)
133- {
134- {{ disposeCallbackName }} (_callbackFunction);
135- _callbackFunction = IntPtr.Zero;
136- }
137+ if (this._callbackFunction != null && !this._callbackFunction.IsInvalid)
138+ this._callbackFunction.Dispose();
139+ this._callbackFunction = null;
137140 }
138141
139- public {{ csReturnType . GetFullyQualifiedName ( ) }} Invoke({{ string . Join ( ", " , invokeParameters ) }} )
142+ public unsafe {{ csReturnType . GetFullyQualifiedName ( ) }} Invoke({{ string . Join ( ", " , invokeParameters ) }} )
140143 {
141144 if (_callbackFunction == null)
142145 throw new System.ObjectDisposedException("{{ csType . Name }} ");
143-
144- {{ csResultImplementation }} {{ invokeCallbackName }} ({{ string . Join ( ", " , callInvokeInteropParameters ) }} );
145- {{ csReturnImplementation }} ;
146+
147+ unsafe
148+ {
149+ System.IntPtr reinteropException = System.IntPtr.Zero;
150+ {{ csResultImplementation }} {{ invokeCallbackName }} ({{ string . Join ( ", " , callInvokeInteropParameters ) }} , &reinteropException);
151+ if (reinteropException != System.IntPtr.Zero)
152+ {
153+ throw (System.Exception)Reinterop.ObjectHandleUtility.GetObjectAndFreeHandle(reinteropException);
154+ }
155+ {{ csReturnImplementation }} ;
156+ }
146157 }
147158
148159 [System.Runtime.InteropServices.DllImport("{{ context . NativeLibraryName }} ", CallingConvention=System.Runtime.InteropServices.CallingConvention.Cdecl)]
149160 private static extern void {{ disposeCallbackName }} (IntPtr callbackFunction);
150161 [System.Runtime.InteropServices.DllImport("{{ context . NativeLibraryName }} ", CallingConvention=System.Runtime.InteropServices.CallingConvention.Cdecl)]
151- private static extern {{ csReturnType . AsInteropTypeReturn ( ) . GetFullyQualifiedName ( ) }} {{ invokeCallbackName }} ({{ string . Join ( ", " , invokeInteropParameters ) }} );
162+ private static unsafe extern {{ csReturnType . AsInteropTypeReturn ( ) . GetFullyQualifiedName ( ) }} {{ invokeCallbackName }} ({{ string . Join ( ", " , invokeInteropParameters ) }} , IntPtr* reinteropException );
152163 }
153164 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
154165 private unsafe delegate IntPtr {{ csBaseName }} Type(IntPtr callbackFunction);
@@ -165,12 +176,19 @@ private void Dispose(bool disposing)
165176 var interopParameters = new [ ] { ( Name : "pCallbackFunction" , CsType : CSharpType . FromSymbol ( context , context . Compilation . GetSpecialType ( SpecialType . System_IntPtr ) ) , Type : CppType . VoidPointer , InteropType : CppType . VoidPointer ) } . Concat ( callbackParameters ) ;
166177 var callParameters = callbackParameters . Select ( p => p . Type . GetConversionFromInteropType ( context , p . Name ) ) ;
167178
179+ CppType interopReturnType = returnType . AsInteropType ( ) ;
180+
168181 string resultImplementation = "" ;
169182 string returnImplementation = "return;" ;
183+ string returnDefault = "return;" ;
170184 if ( invokeMethod . ReturnType . SpecialType != SpecialType . System_Void )
171185 {
172186 resultImplementation = "auto result = " ;
173187 returnImplementation = $ "return { returnType . GetConversionToInteropType ( context , "result" ) } ;";
188+ if ( interopReturnType . Flags . HasFlag ( CppTypeFlags . Pointer ) )
189+ returnDefault = "return nullptr;" ;
190+ else
191+ returnDefault = $$ """ return {{ interopReturnType . GetFullyQualifiedName ( ) }} ();""" ;
174192 }
175193
176194 result . CppImplementationInvoker . Functions . Add ( new (
@@ -179,12 +197,29 @@ private void Dispose(bool disposing)
179197 #if defined(_WIN32)
180198 __declspec(dllexport)
181199 #endif
182- {{ returnType . AsInteropType ( ) . GetFullyQualifiedName ( ) }} {{ invokeCallbackName }} ({{ string . Join ( ", " , interopParameters . Select ( p => $ "{ p . InteropType . GetFullyQualifiedName ( ) } { p . Name } ") ) }} ) {
200+ {{ interopReturnType . GetFullyQualifiedName ( ) }} {{ invokeCallbackName }} ({{ string . Join ( ", " , interopParameters . Select ( p => $ "{ p . InteropType . GetFullyQualifiedName ( ) } { p . Name } ") . Concat ( new [ ] { "void** reinteropException" } ) ) }} ) {
183201 auto pFunc = reinterpret_cast<std::function<{{ itemType . GetFullyQualifiedName ( ) }} ::FunctionSignature>*>(pCallbackFunction);
184- {{ resultImplementation }} (*pFunc)({{ string . Join ( ", " , callParameters ) }} );
185- {{ returnImplementation }}
202+ try {
203+ {{ resultImplementation }} (*pFunc)({{ string . Join ( ", " , callParameters ) }} );
204+ {{ returnImplementation }}
205+ } catch (::DotNet::Reinterop::ReinteropNativeException& e) {
206+ *reinteropException = ::DotNet::Reinterop::ObjectHandle(e.GetDotNetException().GetHandle()).Release();
207+ {{ returnDefault }}
208+ } catch (std::exception& e) {
209+ *reinteropException = ::DotNet::Reinterop::ReinteropException(::DotNet::System::String(e.what())).GetHandle().Release();
210+ {{ returnDefault }}
211+ } catch (...) {
212+ *reinteropException = ::DotNet::Reinterop::ReinteropException(::DotNet::System::String("An unknown native exception occurred.")).GetHandle().Release();
213+ {{ returnDefault }}
214+ }
186215 }
187- """ ) ) ;
216+ """ ,
217+ TypeDefinitionsReferenced : new [ ]
218+ {
219+ CppReinteropException . GetCppType ( context ) ,
220+ CSharpReinteropException . GetCppWrapperType ( context ) ,
221+ CppType . FromCSharp ( context , context . Compilation . GetSpecialType ( SpecialType . System_String ) )
222+ } ) ) ;
188223
189224 result . CppImplementationInvoker . Functions . Add ( new (
190225 Content :
0 commit comments