13

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.

RLH
  • 15,230
  • 22
  • 98
  • 182
  • http://stackoverflow.com/questions/2347260/when-must-we-use-extern-alias-keyword-in-c This seems to be a relevant to you – cvraman Jun 24 '16 at 13:57
  • @cvraman See the last sentence of my question. – RLH Jun 24 '16 at 13:58
  • 1
    Unless you write your own just-in-time compiler: never. It is the jitter that needs to know how to resolve a "call something defined somewhere else" to a real call. The one you use every day only knows a specific set of cases, [DllImport] is one of them. Internal calls to a function defined in the CLR and a COM method call are the other ones. It is not extensible. – Hans Passant Jun 24 '16 at 14:30
  • @HansPassant excellent explaination, as always, Hans! – RLH Jun 24 '16 at 14:33
  • @HansPassant: do you have more info on the "COM method call" case? Sounds like something that could be in an answer, either mine or your own. – Jeroen Mostert Jun 24 '16 at 14:35
  • It is a rather obscure corner case, it applies only to the auto-generated XxxClass class. Which nobody should ever use since it doesn't permit embedding the interop types. – Hans Passant Jun 24 '16 at 14:39
  • @HansPassant: nevertheless, it's another way to locate the implementation, so I added that to my answer. – Jeroen Mostert Jun 24 '16 at 15:41

1 Answers1

13

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.

Jeroen Mostert
  • 27,176
  • 2
  • 52
  • 85