views:

1261

answers:

3

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 containing function pointers from C to C#. I would like to know whether it's the cleanest and/or most efficient way of doing it.

I'm interfacing with a native DLL coded in C that provides the following entry point:

void* getInterface(int id);

You have to pass getInterface(int) one of the following enum values:

enum INTERFACES
{
  FOO,
  BAR
};

Which returns a pointer to a structure containing function pointers like:

typedef struct IFOO
{
  void (*method1)(void* self, int a, float b);
  void (*method2)(void* self, int a, float b, int c);
} IFoo;

And here is how you use it in C:

IFoo* interface = (IFoo*)getInterface(FOO);
interface->method1(obj, 0, 1.0f); // where obj is an instance of an object
                                  // implementing the IFoo interface.

In C# I have a Library class that maps the getInterface(int) entry point using P/Invoke.

class Library
{
  [DllImport("MyDLL"), EntryPoint="getInterface", CallingConvention=CallingConvention.Cdecl)]
  public static extern IntPtr GetInterface(int id);
};

Then I defined:

struct IFoo
{
  public M1 method1;
  public M2 method2;


  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  public delegate void M1(IntPtr self, int a, float b);

  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  public delegate void M2(IntPtr self, int a, float b, int c);
}

And I'm using it this way:

IntPtr address = Library.GetInterface((int)Interfaces.FOO);
IFoo i = (IFoo)Marshal.PtrToStructure(address, typeof(IFoo));

i.method1(obj, 0, 1.0f): // where obj is an instance of an object
                         // implementing the IFoo interface.

I have the following questions:

  1. Is mapping the whole structure less efficient than mapping a single pointer inside the structure using Marshal.GetDelegateForFunctionPointer()?

    Since I mostly don't need all the methods exposed by an interface, I can do (tested and works):

    unsafe
    {
      IntPtr address = Library.GetInterface(id);
      IntPtr m2address = new IntPtr(((void**)address.toPointer())[1]);
    
    
      M2 method2 = (M2)Marshal.GetDelegateForFunctionPointer(m2address, typeof(M2));
    
    
      method2(obj, 0, 1.0f, 1);
    }
    
  2. When mapping the whole structure at once using Marshal.PtrToStructure(), is there a less verbose way than what I described? I mean less verbose than having to define the delegate types for every methods etc?


EDIT: For the sake of clarity and completeness, in the code snippets above, obj is an instance obtained with the void* createObject(int type) entry point.


EDIT2: One advantage of method 1) is that Marshal.GetDelegateForFunctionPointer() is only available starting from .NET Framework 2.0. However, Marshal.PrtToStructure() has always been available. That said, I'm not sure it's worth ensuring 1.0 compatibility nowadays.


EDIT3: I tried to inspect the generated code using Reflector but it doesn't give much information since all the interesting details are done in helper functions like PtrToStructureHelper and are not exposed. Then, even if I could see what's done in the framework internals, then the runtime has the opportunity to optimize things away and I don't know exactly what, why and when :)

However, I benchmarked the two approaches described in my question. The Marshal.PtrToStructure() approach was slower by a factor around 10% compared to the Marshal.GetDelegateForFunctionPointer() approach; that whith a structure containing IntPtrs for all the functions that are not of interest.

I also compared the Marshal.GetDelegateForFunctionPointer() with my own rolled marshaller: I align a struct representing the call stack, pin it in memory, pass its address to the native side where I use a trampoline coded in asm so that the call function uses the memory area as its parameter stack (this is possible since the cdecl x86 calling convention passes all the function parameters on the stack). Timings were equivalent.

+1  A: 

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.

John Knoeller
About 1) I don't really know whether it's possible to check what's really done in the end: like the optimizer may figure out that only 1 delegate of the structure is being used. Anyway at least it looks clean enough.
Gregory Pakosz
@Gregory I think that's unlikely. But you could use .NET reflector to decompile to code and find out for sure.
John Knoeller
+1  A: 

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);
        }
    }
}
280Z28
Well, this is how I'm doing it. It's just that this kind of "pretty-wrapping" was irrelevant to the question. Then I know I didn't explain that in details, but `self` is not the pointer to the interface structure. It's really a `this` pointer.
Gregory Pakosz
The native library has a `void* obj = createObject(int type)` entry point. You use it to instantiate types, then if the type you instantiated implements the IFoo interface (`bool implements(void* obj, int iface)` returns `true` for `obj` and `FOO`), you are allowed to call `((IFoo*)getInterface(FOO))->method1(obj, 0, 1.0f);`
Gregory Pakosz
This simplest alteration would be adding an `IntPtr self` parameter to `GetFooInterface`. For a complex wrapper like that, I'd actually create `Is<TInterface>` and `As<TInterface>` methods to perform the casts. If I went a step further, I'd dynamically create implementation classes so the C# `is` and `as` operators work seamlessly.
280Z28
What do you mean by "dynamically create implementation classes"?
Gregory Pakosz
Rather than explicitly write the NativeFooWrapper class, I'd use the `System.Reflection.Emit` classes to dynamically create an object wrapper type that implements `IFoo` and/or `IBar` and/or any other interfaces implemented by the native object. The generator code would call `implements()` for each of the known interface types to make sure the object implemented exactly the correct set of interfaces.
280Z28
That's an interesting approach. Well everything is coded already, with full fledged C# classes and interfaces. For instance, the `FooBar` concrete type extends the abstract `NativeObject` type(that takes care of wrapping the native `self` pointer) and implements both `IFoo` and `IBar`. So with the code generation approach, instead of just doing `new FooBar()` users would have to call a factory method and would get back an `Object` instance. Then they would have to use the `as` operator with the needed interface right? Somehow I also feel like it makes documenting harder.
Gregory Pakosz
+1  A: 

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.

Laurent Etiemble
Ok it seems to be a consensus there: when marshalling the whole structure, you pay for what you may not use. About the pointer size, `new IntPtr(((void**)address.toPointer())[1])` gets it right whatever the size.
Gregory Pakosz
And yes, the only less verbose option I'm using when marshalling the whole structure is to define only the delegates I need and use raw `IntPtr` for the remaining entry points
Gregory Pakosz