简体   繁体   English

如何将CIL代码插入C#

[英]How to insert CIL code to C#

是否可以将IL代码插入C#方法?

I just posted a utility which allows entire C# function bodies to be automatically replaced with inline IL, using a custom attribute. 我刚发布了一个实用程序 ,它允许整个C#函数体使用自定义属性自动替换为内联IL。 Like similar utilities, this works via the ILDASM/ILASM round-trip which can be set up as a post-build step. 与类似的实用程序一样,这可以通过ILDASM / ILASM往返进行,可以将其设置为构建后步骤。 The tool also adjusts the PDB in order to preserve single-stepping and setting breakpoints on individual IL instructions in the debugger. 该工具还调整PDB,以便在调试器中的单个IL指令上保留单步执行和设置断点。 It's different from some of the other round-trip IL inliners in that it (only) substitutes for entire function bodies, like this: 它与其他一些往返IL内联器的不同之处在于它(仅)替代整个函数体,如下所示:

    class MyClass
    {
        [ILFunc(@"
    .locals init ([0] int32 i_arg)
        ldc.i4.3
        ret
    ")]
        int MyFunc(int i_arg)
        {
            return 3;
        }
    };

For highly performance-critical methods, I tried using DynamicMethod to improve upon compiler-generated IL, but found that the benefit is lost due to the delegate-calling overhead. 对于高度性能关键的方法,我尝试使用DynamicMethod来改进编译器生成的IL,但发现由于委托调用开销而导致的好处丢失了。 Inline IL gives the the beneft of hand-tuned IL without that hit, assuming there are no runtime customizations that you would truly need DynamicMethod for. 假设没有您真正需要DynamicMethod运行时自定义,内联IL给出了手动调整IL的优势而没有命中。

The complete source code is located at http://www.glennslayden.com/code/c-sharp/inline-il 完整的源代码位于http://www.glennslayden.com/code/c-sharp/inline-il

If inline IL (in the same spirit of inline assembly supported by C and C++ compilers) is what you're looking for, this can be achieved using post-compilation round-trip compiling. 如果您正在寻找内联IL(与C和C ++编译器支持的内联汇编的精神相同),则可以使用后编译往返编译来实现。

Mike Stall has once written a tool for that , as far as I know it's fairly mature: Mike Stall曾经为此编写过一个工具 ,据我所知它已经相当成熟了:

Other than that, you could use F# which supports Inline IL. 除此之外,您可以使用支持Inline IL的F#。

DynamicMethod is the lightweight way to accomplish this at runtime. DynamicMethod是在运行时完成此任务的轻量级方法。

The Microsoft C# compiler doesn't support injection of IL at compile-time, but a code-weaving tool could do so as a post-compile step. Microsoft C#编译器不支持在编译时注入IL,但代码编织工具可以作为后编译步骤。

The tool you need is called Cecil and is a part of the Mono project. 您需要的工具称为Cecil ,是Mono项目的一部分。

You can get more information about it here: http://www.mono-project.com/Cecil 您可以在此处获得有关它的更多信息: http//www.mono-project.com/Cecil

Quoted from the website above: 引自上面的网站:

Cecil is a library written by Jb Evain ( http://evain.net/blog/ ) to generate and inspect programs and libraries in the ECMA CIL format. Cecil是由Jb Evain( http://evain.net/blog/ )编写的库,用于生成和检查ECMA CIL格式的程序和库。 It has full support for generics, and support some debugging symbol format. 它完全支持泛型,并支持一些调试符号格式。

In simple English, with Cecil, you can load existing managed assemblies, browse all the contained types, modify them on the fly and save back to the disk the modified assembly. 用简单的英语,使用Cecil,您可以加载现有的托管程序集,浏览所有包含的类型,动态修改它们并将修改后的程序集保存回磁盘。

I'll add my own tool to the list of solutions already provided here: InlineIL.Fody . 我将自己的工具添加到此处已提供的解决方案列表中: InlineIL.Fody

This uses the Fody assembly weaving tool to modify the assembly at build time. 这使用Fody组装编织工具在构建时修改组件。 Which means all you have to do is install a NuGet package, add a config file to your project and you're done. 这意味着你要做的就是安装一个NuGet包,在你的项目中添加一个配置文件,你就完成了。

You're then provided with a simple and type-safe API to emit IL instructions, which you can mix with C# code. 然后,您将获得一个简单且类型安全的API来发出IL指令,您可以将其与C#代码混合使用。 I believe it's easier to write IL in this way than writing text, and it's also more convenient than ILGenerator since each opcode gets its own method with relevant overloads only. 我认为用这种方式编写IL比写文本更容易,而且它比ILGenerator更方便,因为每个操作码只有相关的重载才能获得自己的方法。

Here's an example, with using static InlineIL.IL.Emit; 这是一个例子, using static InlineIL.IL.Emit; :

public static void ZeroInit<T>(ref T value)
    where T : struct
{
    Ldarg(nameof(value));
    Ldc_I4_0();
    Sizeof(typeof(T));
    Unaligned(1);
    Initblk();
}

This shows how to access the initblk instruction which C# doesn't currently expose. 这显示了如何访问C#当前未公开的initblk指令。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM