在我问的另一个问题中,出现了一条评论,表明.NET框架的Array.Copy方法使用了非托管代码.我用Reflector挖掘并发现Array.Copy方法重载的签名之一定义如下:
[MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);
Run Code Online (Sandbox Code Playgroud)
看了这个之后,我有点困惑.我混淆的来源是extern修饰符,意思是(MSDN链接):
extern修饰符用于声明从外部实现的方法.
但是,方法声明也用一个MethodImplOptions.InternalCall属性来装饰,它表示(MSDN链接):
指定内部调用.内部调用是对在公共语言运行时本身内实现的方法的调用.
任何人都可以解释这个看似明显的矛盾吗?
Sam*_*ell 50
我本来会评论leppie的帖子,但它有点长.
我目前正在开发一个实验性的CLI实现.在许多情况下,如果不了解内部如何实施虚拟机,则无法实现公开的方法(或属性).一个例子是OffsetToStringData,它需要知道内存管理器如何分配字符串.
对于这样的情况,如果没有C#代码来表达方法,则可以在JIT进程内部以特殊方式处理对方法的每次调用.作为示例,在将call字节代码ldc.i4传递给本机代码生成器之前,用(加载常量整数)替换字节代码.该InternalCall标志表示"该方法的体在由运行时自身一种特殊的方式进行处理." 可能有也可能没有实际的实现 - 在我的代码中的几种情况下,调用被JIT 视为内在的.
在其他情况下,JIT可能具有可用的特殊信息,允许对方法进行大量优化.一个例子是这些Math方法,即使这些方法可以在C#中实现,指定InternalCall使它们有效地具有内在性也具有显着的性能优势.
在C#中,方法必须有一个体,除非它是abstract或extern.这extern意味着一般的"你可以用C#代码调用这个方法,但它的主体实际上是在其他地方定义的." 当JIT到达对extern方法的调用时,它会查找找到正文的位置,并根据结果以不同的方式运行.
DllImport属性指示JIT创建P/Invoke存根以调用本机代码实现.InternalCall标志指示JIT以自定义方式处理呼叫.lep*_*pie 17
InternalCall 框架提供的手段.
extern 说你没有提供代码.
extern 可以在两种一般情况下使用,例如上面的,或者使用p/invoke.
使用p/invoke,您只需告诉方法获取实现的位置.
| 归档时间: |
|
| 查看次数: |
7942 次 |
| 最近记录: |