有此&明确的此调用约定 [英] HasThis & ExplicitThis calling conventions

查看:51
本文介绍了有此&明确的此调用约定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在HasThis 和 ExplicitThis 调用约定.cs,0e671adbca70e090"rel =" nofollow noreferrer>.NET Framework参考源,因此我开始怀疑:

I come across HasThis and ExplicitThis calling conventions on .NET Framework reference source, and thus I begin to wonder:

  • 它们何时由编译器设置?
  • 是否有使用此调用约定组合的示例(在现实世界"托管程序中)?

MSDN 将它们描述为:

ExplicitThis

指定签名是功能指针签名,表示对实例或虚拟方法(不是静态方法)的调用.如果设置了 ExplicitThis ,则还必须设置 HasThis .传递给被调用方法的第一个参数仍然是 this 指针,但是第一个参数的类型现在是未知的.因此,描述 this 指针的类型(或类)的令牌已显式存储在其元数据签名中.

Specifies that the signature is a function-pointer signature, representing a call to an instance or virtual method (not a static method). If ExplicitThis is set, HasThis must also be set. The first argument passed to the called method is still a this pointer, but the type of the first argument is now unknown. Therefore, a token that describes the type (or class) of the this pointer is explicitly stored into its metadata signature.

有此

指定实例或虚拟方法(不是静态方法).在运行时,被调用的方法会传递一个指向目标对象的指针作为其第一个参数( this 指针).存储在元数据中的签名不包括该第一个参数的类型,因为该方法是已知的,并且可以从元数据中发现其所有者类.

Specifies an instance or virtual method (not a static method). At run-time, the called method is passed a pointer to the target object as its first argument (the this pointer). The signature stored in metadata does not include the type of this first argument, because the method is known and its owner class can be discovered from metadata.

这是一个示例程序,我使用以下这些位集生成了一个类和构造函数:

Here is a sample program I wrote to generate a class and constructor using these bits set:

const string FileName = "MyDynamicLib.dll";
AppDomain currentDomain = AppDomain.CurrentDomain;

AssemblyName assemblyName = new AssemblyName(assemblyName: "MyAssembly");
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(
                                                                      name  : assemblyName,
                                                                      access: AssemblyBuilderAccess.RunAndSave
                                                                     );
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(
                                                                  name          : "MyModule",
                                                                  fileName      : FileName,
                                                                  emitSymbolInfo: true
                                                                 );

TypeBuilder typeBuilder = moduleBuilder.DefineType(
                                                   name: "MyClass",
                                                   attr: TypeAttributes.Public | TypeAttributes.BeforeFieldInit
                                                  );
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
                                                                      attributes       : MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                                      callingConvention: CallingConventions.HasThis | CallingConventions.ExplicitThis,
                                                                      parameterTypes   : null
                                                                     );
constructorBuilder.GetILGenerator().Emit(opcode: OpCodes.Ret);
typeBuilder.CreateType();

assemblyBuilder.Save(
                     assemblyFileName      : FileName,
                     portableExecutableKind: PortableExecutableKinds.Required32Bit,
                     imageFileMachine      : ImageFileMachine.I386
                    );


到目前为止所知:
无法使用C#语法更改方法的调用约定.仅在IL级别上才可以实现,也可以使用反射发射API.
HasThis Standard 是最常用的,无需解释.
另一方面,将 VarArgs 位设置为 __ arglist 方法:


What is known so far:
It is not possible to change method's calling convention using C# syntax. This is only possible at IL level, also using Reflection emit API.
HasThis and Standard are the most commonly used, there is no need to explain these.
VarArgs bit, on the other hand, it is set for __arglist method:

static void VariadicMethod(__arglist)

推荐答案

我将尝试仔细回答,因为它是ECMA中最不清晰的主题之一,但也许我可以对此有所启发.

I will try to answer carefully because it's one of the most less clear subject in ECMA but maybe I will be able to shed some light on this.

您可以跳到返回您的问题"部分以查看最终答案.

You can skip to "Back to your question" section to see the final answer.

答案有点长,因为我想带个参考,所以我将不再引用我的意见.我希望它将是可以理解的.如果没有,我将在答案中加上更多解释.

引号中的重点是我的.一些报价被删掉了.

函数指针的签名中的EXPLICITTHIS(0x40)位只能设置:MethodDefSig之前是FNPTR

The EXPLICITTHIS (0x40) bit can be set only in signatures for function pointers: signatures whose MethodDefSig is preceded by FNPTR

来自CoreCLR

EXPLICITTHIS和本地调用转换仅适用于独立sig(用于calli)

EXPLICITTHIS and native call convs are for stand-alone sigs only (for calli)

函数指针是一种调用非托管方法的方法.

Function pointers is a way to call unmanaged methods.

也可以通过函数指针来调用非托管方法.

Unmanaged methods can also be called via function pointers.

可以通过 calli 指令

方法指针应将入口点的地址存储到其签名的方法中是方法指针类型的 method-signature-compatible-with .可以通过将方法指针与 calli 一起使用来调用方法操作说明.

Method pointer shall store the address of the entry point to a method whose signature is method-signature-compatible-with the type of the method pointer. A method can be called by using a method pointer with the calli instruction.

关于它的更多信息

正确的CIL要求函数指针包含其签名的方法的地址与 callsitedescr 指定的方法签名兼容和参数正确地与目标函数的此指针的类型相对应(如果需要),并且参数.为了进行签名匹配,将HASTHIS和EXPLICITTHIS标志设置为忽略所有其他项目在两个签名中必须相同.

Correct CIL requires that the function pointer contains the address of a method whose signature is method-signature compatible-with that specified by callsitedescr and that the arguments correctly correspond to the types of the destination function’s this pointer, if required, and parameters. For the purposes of signature matching, the HASTHIS and EXPLICITTHIS flags are ignored; all other items must be identical in the two signatures.

还有

calli 指令包括一个呼叫站点描述,其中包含有关本机呼叫的信息用来调用该方法的约定.正确的CIL代码应在与正在调用的方法的调用约定相匹配的 calli 指令.

The calli instruction includes a call site description that includes information about the native calling convention that should be used to invoke the method. Correct CIL code shall specify a calling convention in the calli instruction that matches the calling convention for the method that is being called.

呼叫站点说明

致电网站描述(表示为独立呼叫签名的元数据令牌),该描述提供:•传递的参数数量.•每个参数的数据类型.•它们在调用堆栈中的放置顺序.•要使用的本地调用约定

Ccall site description (represented as a metadata token for a stand-alone call signature) that provides: • The number of arguments being passed. • The data type of each argument. • The order in which they have been placed on the call stack. • The native calling convention to be used

方法签名兼容-均值

方法签名类型T与方法签名类型U兼容,如果并且仅在以下情况下:1.对于每个签名,独立地,如果签名用于实例方法,则它带有这种类型.[注意:对于实例方法指针的签名始终如此.由ldvirtftn指令产生.2. T和U的调用约定应完全匹配,而忽略区别在静态方法和实例方法之间(即,不处理this参数(如果有的话)专门).

A method signature type T is method-signature compatible-with a method signature type U if and only if: 1. For each signature, independently, if the signature is for an instance method it carries the type of this. [Note: This is always true for the signatures of instance method pointers produced by ldvirtftn instruction. 2. The calling conventions of T and U shall match exactly, ignoring the distinction between static and instance methods (i.e., the this parameter, if any, is not treated specially).


回到您的问题

  • 它们何时由编译器设置?
  • 是否有使用此调用约定组合的示例(在现实世界"托管程序中)?

ExplicitThis 只能在通过 calli 指令调用函数指针时使用.

ExplicitThis can be using only when calling function pointers via calli instruction.

AFAIK C#编译器生成 calli 指令,因此您将看不到任何设置此位的C#代码.

AFAIK the C# compiler not generating calli instruction, so you will not see any C# code that set this bit.

C#编译器将不会生成Calli说明

罗斯林源代码

EXPLICITTHIS和本机调用转换均适用于标准仅限单独信号(用于Calli)

ECMA

这篇关于有此&明确的此调用约定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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