Sorry for the verbose introduction that follows. I need insight from someone knowing P/Invoke internals better than I do.
Here is how I\'m marshalling structures cont
Here's what I would start with.
Usage:
IFoo foo = UnsafeNativeMethods.GetFooInterface();
foo.Method1(0, 1.0f);
Implementation:
internal interface IFoo
{
void Method1(int a, float b);
void Method2(int a, float b, int c);
}
internal static class UnsafeNativeMethods
{
public static IFoo GetFooInterface()
{
IntPtr self = GetInterface(InterfaceType.Foo);
NativeFoo nativeFoo = (NativeFoo)Marshal.PtrToStructure(self, typeof(NativeFoo));
return new NativeFooWrapper(self, nativeFoo.Method1, nativeFoo.Method2);
}
[DllImport("mydll.dll", EntryPoint = "getInterface", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GetInterface(InterfaceType id);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void Method1Delegate(IntPtr self, int a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void Method2Delegate(IntPtr self, int a, float b, int c);
private enum InterfaceType
{
Foo,
Bar
}
private struct NativeFoo
{
public Method1Delegate Method1;
public Method2Delegate Method2;
}
private sealed class NativeFooWrapper : IFoo
{
private IntPtr _self;
private Method1Delegate _method1;
private Method2Delegate _method2;
public NativeFooWrapper(IntPtr self, Method1Delegate method1, Method2Delegate method2)
{
this._self = self;
this._method1 = method1;
this._method2 = method2;
}
public void Method1(int a, float b)
{
_method1(_self, a, b);
}
public void Method2(int a, float b, int c)
{
_method2(_self, a, b, c);
}
}
}
I don't know that answer to your question 1. I'd expect that Marshal.PtrToStructure()
is implemented in terms of the other Marshal primitives, so it would be more efficient to just use the single Marshal.GetDelegateForFunctionPointer
. But that's just a guess - worth what you paid for it.
As for your question 2. No, there is no less verbose way to do this. There is a MORE verbose way. You can use the old style MIDL compiler to build a type library for your dll and the load that type library. But the available marshaling options for MIDL are quite a bit more limited that what you can describe in C#. And the MIDL compler is pretty hard to work with, you would probably end up having to write another unmanaged DLL to do the interop between managed code and your target dll.
For point 1:
Marshal.GetDelegateForFunctionPointer()
is more simple if your structure contains a lot of function pointers and you use only a few. A (major) drawback is that you have to compute the offset to the function pointer by hand (note that pointer size differs on 32/64 bits platform). A structure is more easy to use but marshals more data.
For point 2:
I don't think a less verbose approach is possible. You may only define delegates for the function you want to use, and use a dummy delegate for the function pointers you don't want to use. This way, the marshaling will perform ok, but you end with a structure containing non-callable delegates.