什么时候使用extern关键字而不使用[DllImport]属性合适? [英] When is it appropriate to use the extern keyword without using the [DllImport] attribute?

查看:175
本文介绍了什么时候使用extern关键字而不使用[DllImport]属性合适?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,当我注意到 extern 关键字文档声明:


外部修饰符用于声明在外部实现的方法。当您使用Interop服务调用非托管代码时,extern修饰符的 常见用法 带有DllImport属性。


引起我注意的是该文档指出 extern 的常用是它与DllImport属性一起使用。这意味着存在其他不需要DllImport的用例。我不必将许多外部非托管库集成到我的应用程序中,但在所有情况下,链接方法都是使用DllImport定义的。



我搜索了多个查询通过Google和MSDN,我找不到在没有将方法定义为从非托管dll导入外部方法的情况下何时使用 extern 关键字的案例或解释。 / p>

如何以及何时使用 extern 关键字而不定义 [DllImport(...)] 方法定义上的属性?



请注意,这并非专门用于 extern 定义别名时。这是该关键字的另一种用法,这种情况在另一篇文章中中概述了在MSDN C#语言参考中。

解决方案

我要使用它的一种情况是,如果我是实现Microsoft的开发人员对CLR本身中定义的方法的调用。就像在 GC._WaitForFullGCApproach 中一样:

  [MethodImpl(MethodImplOptions.InternalCall)] 
私有静态外部整数_WaitForFullGCApproach(int millisecondsTimeout);

注意:否 DllImport 。当然,这有点作弊-这仍然是对非托管方法的调用,只是没有显式引用DLL。但是,凡人不能调用此类代码,因为它仅在 mscorlib 程序集中有效。



InternalCall 是为COM生成的互操作类型:

 命名空间Microsoft.Office。 Interop.Excel {
[DefaultMember( _ Default)]
[ClassInterface(0)]
[ComSourceInterfaces( Microsoft.Office.Interop.Excel.AppEvents\0)]
[Guid( 00024500-0000-0000-C000-000000000046)]
[TypeLibType(2)]
[ComImport]
公共类ApplicationClass {
// ...
[DispId(302)]
[MethodImpl(MethodImplOptions.InternalCall)]
公共虚拟外部void Quit();
// ...
}
}

属性允许运行时将方法调用解析为对COM接口的调用。显然,在 mscorlib 之外有效使用 InternalCall 。您通常不会自己用C#编写这样的代码。



C#语言规范比MSDN更加详细:


extern 修饰符通常与 DllImport
属性(第17.5.1节),允许
DLL(动态链接库)实现外部方法。执行环境可以支持
其他机制,从而可以提供
的外部方法的实现。


来自实现从立场上来说,将方法标记为 extern 仅具有将方法的RVA(相对虚拟地址)设置为0的作用,将其标记为没有实现。诸如 DllImport (和 MethodImpl )之类的属性对于向运行时描述如何定位方法的实际实现是必需的。 ECMA-335的第I.9.4节方法实现元数据(以及 DllImport InternalCall



C#编译器将允许您将方法标记为 extern 使用任何属性来指示实现所在的位置,但是具有这种方法的任何类型在运行时都将导致 TypeLoadException


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.

解决方案

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.

这篇关于什么时候使用extern关键字而不使用[DllImport]属性合适?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆