views:

288

answers:

1

Hi,

When creating COM interface declarations in C# are there any "rules" you have to stick to? I think there are and would like to get some info on it. For example I'm toying around with the ITaskbarList, ITaskbarList2 and ITaskbarList3 interfaces and it seems to me that I

  • Have to declare the order of the members in the manages implementation exactly in the order that they appear in the unmanaged interface declaration.

For example the following appears to work just fine

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
}

While reordering the members breaks the functionality

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void DeleteTab([In] IntPtr hwnd);
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
}
  • Have to declare inherited unmanaged interfaces in a single managed interface declaration instead of using inheritance on the managed interfaces. I want to declare each of the unmanaged interfaces in their own managed interface (complete with Guid attributes etc) and use inheritance inbetween then, instead of redeclaring the parent declarations in each new interface.

For example, this doesn't appear to work

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
}

[ComImport]
[Guid("602D4995-B13A-429B-A66E-1935E44F4317")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList2
    : ITaskbarList
{
    void MarkFullscreenWindow(
        [In] IntPtr hwnd,
        [In, MarshalAs(UnmanagedType.Bool)] bool fullscreen);
}

Instead I'm forced to do the following

[ComImport]
[Guid("602D4995-B13A-429B-A66E-1935E44F4317")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList2
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
    void MarkFullscreenWindow(
        [In] IntPtr hwnd,
        [In, MarshalAs(UnmanagedType.Bool)] bool fullscreen);
}

I.e declare it in a single interface while still taking the member order into concideration.

So what are the guidelines for declaring managed interfaces for their unmanaged counterparts? Is there anyway to achive what I want, it interface inheritance on the managed side + declare the memebers in any order I want (I really just want to sort them alphabetically)

+1  A: 

Your discoveries are caused by the same thing: vtables. You can't change the vtable order, and interfaces that inherit from other interfaces always have all the base entries in the vtable as well. So, the rules you're looking for is "make sure the vtable is the same."

jeffamaphone
So .net doesn't pamper me with automatic mappings of the vtable entries based on names? Anyway to configure it using attributes etc? Also why wouldn't the inheritance work? Surly it would concatenate the vtables along the inheritance chain? I.e first the entries for ITaskbarList then for ITaskbarList2 and then for ITaskbarList3.. or do I only end up with the entries from the last interface in ITaskbarList3 despite the inheritance?
TheCodeJunkie
<quote>interfaces that inherit from other interfaces always have all the base entries in the vtable as well</quote>Wouldn't this mean that if the order of the members in each of the interface is correct then the vtable entries for an interface, that inherits another interface, would end up correct?
TheCodeJunkie
I'll answer my own follow up question. The .NET interop does not support interface inheritance, thus you have to redefine the parent interface members in the child interface(s).
TheCodeJunkie