What does MethodImplAttribute(InternalCall, Runtim

2020-06-16 03:38发布

问题:

In Windows API Code Pack for .NET Framework, many methods of COM Interop interfaces are decorated with MethodImplAttribute, for example:

internal interface IShellItem
{
    [PreserveSig]
    [MethodImpl(
        MethodImplOptions.InternalCall,
        MethodCodeType = MethodCodeType.Runtime)]
    HResult BindToHandler(
        [In] IntPtr pbc, [In] ref Guid bhid, [In] ref Guid riid,
        [Out, MarshalAs(UnmanagedType.Interface)] out IShellFolder ppv);

Documentation for MethodImplOptions.InternalCall value says:

The call is internal, that is, it calls a method that is implemented within the common language runtime.

Documentation for MethodCodeType.Runtime says:

Specifies that the method implementation is provided by the runtime.

But, if I understand correctly, neither statement is correct. IShellItem is implemented in shell32.dll, according to MSDN. shell32.dll is not a part of CLR. What's interesting, not all methods have the MethodImplAttribute. IShellFolder does, IShellLinkW doesn't, IShellLibrary does, IPersistStream doesn't etc.

Why is MethodImplAttribute applied to some of the COM Interop interfaces? What does it mean in this case and how does it modify behavior of interop?

回答1:

It is just a side-effect from the way the Microsoft programmer obtained the interface declaration. Some of the shell interfaces are available in a type library, like IShellItem, so the easiest way to get them into source code is to run Tlbimp.exe to generate the interop library and a disassembler to decompile the assembly into C# code. Which also brings in the extra attributes that Tlbimp.exe generates, like [MethodImpl].

Other interfaces are not available in a type library, like IShellLinkW and IPersistStream, nor can a type library be generated from the IDL so the programmer had no choice but to type them in himself. He skipped the unnecessary stuff.

And no, [MethodImpl] isn't critical here. These are interface types so there is no method anyway. Tlbimp.exe just isn't terribly sophisticated about it.