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

1

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.

Hine answered 24/6, 2016 at 13:49 Comment(7)
#2347760 This seems to be a relevant to youPrepositor
@Prepositor See the last sentence of my question.Hine
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.Nerte
@HansPassant excellent explaination, as always, Hans!Hine
@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.Chalkboard
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.Nerte
@HansPassant: nevertheless, it's another way to locate the implementation, so I added that to my answer.Chalkboard
C
14

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.

Chalkboard answered 24/6, 2016 at 14:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.