I've implemented a very simple custom marshaler for an API:
Custom Marshaler:
private sealed class JuliaWrapperMarshaller : ICustomMarshaler
{
object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData) => (JuliaWrapper)pNativeData;
[other methods removed]
}
API:
[DllImport(@"libjulia.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(JuliaWrapperMarshaller))]
public static extern JuliaWrapper jl_eval_string(string str);
And this works fine when the jl_eval_string
method returns a non-zero IntPtr. I can convert it to my return object JuliaWrapper
and all is well.
The problem comes when I execute jl_eval_string
with invalid parameters and it returns a zero IntPtr.
I want to handle this in my JuliaWrapper
object and automatically call 'get last error'. However I don't get the chance to, because the ICustomMarshaler.MarshalNativeToManaged
method is never invoked when the jl_eval_string
method returns 0x0000
Based on Hans' comment, this isn't possible.
In order to achieve similar functionality, I created public/private shadow functions which return my wrapper class.
The implicit operator
function receives the IntPtr which is 0 or otherwise, and calls the constructor of my wrapper class, which I then have code in to handle calling 'GetLastError' if the IntPtr is 0.