When is it appropriate to use the extern keyword without using the [DllImport] attribute?

走远了吗. 提交于 2020-01-01 09:24:08

问题


I was re-reading through some .Net documentation today when I noticed that the first portion of the extern keywords documentation claims:

The extern modifier is used to declare a method that is implemented externally. A common use of the extern modifier is with the DllImport attribute when you are using Interop services to call into unmanaged code.

What caught my attention was that the document states that "a common use" of extern is that it is used with the DllImport attribute. This implies that there are other use-cases where DllImport is not required. I've not had to integrate many external, non-managed libraries into my applications but in all cases the linked methods were defined with DllImport.

I've searched multiple queries through Google and MSDN and I can't find a case or explanation of when the extern keyword would be used without defining the method as an external method import from an unmanaged dll.

How, and when, would you use the extern keyword without defining the [DllImport(...)] attribute on the method definition?

Please note, this is not specific to using extern when defining aliases. That is a different use of the keyword and that case is outlined in a different article within the MSDN C# language reference.


回答1:


One case where I'd use it is if I were a Microsoft developer implementing a call to a method defined in the CLR itself. Like in GC._WaitForFullGCApproach:

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern int _WaitForFullGCApproach(int millisecondsTimeout);

Note: no DllImport. Of course this is cheating a bit -- this is still a call to an unmanaged method, just not with an explicit reference to a DLL. Mere mortals cannot invoke such code, though, since it's valid only in the mscorlib assembly.

Another application of InternalCall is in interop types generated for COM:

namespace Microsoft.Office.Interop.Excel {
    [DefaultMember("_Default")]
    [ClassInterface(0)]
    [ComSourceInterfaces("Microsoft.Office.Interop.Excel.AppEvents\0")]
    [Guid("00024500-0000-0000-C000-000000000046")]
    [TypeLibType(2)]
    [ComImport]
    public class ApplicationClass {
        // ...
        [DispId(302)]
        [MethodImpl(MethodImplOptions.InternalCall)]
        public virtual extern void Quit();
        // ...
    }
}

The attributes allow the runtime to resolve the method call as an invocation to a COM interface. This use of InternalCall is valid outside mscorlib, obviously. You would not typically write such code in C# yourself; it's generated on demand when you add a COM type library as a reference.

The C# language specification goes into slightly more detail than the MSDN:

The extern modifier is typically used in conjunction with a DllImport attribute (§17.5.1), allowing external methods to be implemented by DLLs (Dynamic Link Libraries). The execution environment may support other mechanisms whereby implementations of external methods can be provided.

From an implementation standpoint, marking a method extern only has the effect of setting the RVA (relative virtual address) of the method to 0, marking it as having no implementation. Attributes like DllImport (and MethodImpl) are necessary to describe to the runtime how to locate the method's actual implementation. This is described in secion I.9.4 of ECMA-335, "Method implementation metadata" (and DllImport and InternalCall seem to be the only ways currently available).

The C# compiler will allow you to mark a method as extern and not use any attribute to indicate where the implementation lives, but any type with such a method will result in a TypeLoadException at runtime.



来源:https://stackoverflow.com/questions/38015024/when-is-it-appropriate-to-use-the-extern-keyword-without-using-the-dllimport-a

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!