从 C++/CLI 项目创建纯 MSIL 程序集? [英] Creating a pure MSIL assembly from a C++/CLI project?

查看:13
本文介绍了从 C++/CLI 项目创建纯 MSIL 程序集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用/clr:pure 和/clrimagetype:pure 标志从 C++/CLI 项目创建纯 MSIL 程序集,但是,输出程序集专门针对 x86.

I am trying to create a pure MSIL assembly from a C++/CLI project using /clr:pure and /clrimagetype:pure flags, however, the output assembly specifically targets x86.

我是否遗漏了任何可能阻止我的项目仅编译为 MSIL 的内容?

Am I missing anything that might be preventing my project to be compiled as MSIL only?

推荐答案

您可以使用 C++/CLI 创建 AnyCPU dll,但在最简单的情况下,您将不能使用 MFC、ATL 或 CRT.但是,如果您只想在 C++/CLI 中编写纯托管 .NET 代码,包括托管指针(/clr:safe 不允许),并获得 C++/CLI 编译器,请继续阅读:

You can create an AnyCPU dll with C++/CLI, but in the simplest case, you will not be able to use MFC, ATL or the CRT. However, if you just want to write pure managed .NET code in C++/CLI, including managed pointers (which /clr:safe does not allow), and get the more elaborate code optimization of the C++/CLI compiler, read on:

  1. 为获得最佳结果,请从托管类库项目模板中新建一个项目.将 DLL 类库的 C++/CLI 项目属性设置为 /clr:pure.这是在 Visual Studio 2010 中的 Configuration Properties 页面上.
  2. 在C/C++面板上,将Omit Default Library Name设置为Yes/Zl
  3. 对于链接器,禁用增量链接链接库依赖
  4. 在链接器的高级"页面上,我将目标机器设置为 Not Set,将 CLR Image Type 设置为 Force Pure IL Image/CLRIMAGETYPE:PURE,但有些显然,这些设置中的一部分不受尊重,因为 32BIT+ 标志仍由 PE32 标头中的链接器设置.
  5. 因此,在您的构建中添加一个 corflags 步骤.执行此操作的最佳方法是退出 Visual Studio 并使用文本编辑器编辑 vcxproj 文件.在文件底部,添加:
  1. For best results, start with a fresh project from the managed class library project template. Set the C++/CLI project properties for the DLL class library to /clr:pure. This is on the Configuration Properties page in Visual Studio 2010.
  2. On the C/C++ panel, set Omit Default Library Name to Yes /Zl
  3. For the linker, disable Incremental Linking and Link Library Dependencies
  4. On the linker's "Advanced" page, I set the Target Machine to Not Set and the CLR Image Type to Force Pure IL Image /CLRIMAGETYPE:PURE, but some of these aparently settings aren't honored, since the 32BIT+ flag is still set by the linker in the PE32 header.
  5. Therefore, add a corflags step to your build. The best way to do this is to exit Visual Studio and edit your vcxproj file with a text editor. At the bottom of the file, add:

    <!-- at the bottom of the file... -->
    <Target Name="AfterBuild">
        <Exec Command="corflags $(TargetPath) /32BIT-" />
    </Target>
</Project>

这会运行 corflags 工具来关闭 DLL 中的 32BIT 标志.确保 corflags.exe 工具在您的路径中可用.

  • 最后,将存根条目添加到您的 C++/CLI 源文件中.这是模块静态构造函数.对我有用的是将以下内容放在任何名称空间之外:

    This runs the corflags tool to turn off the 32BIT flag in your DLL. Make sure that the corflags.exe tool is available in your path.

  • Finally, add a stub entry to your C++/CLI source file. This is the module static constructor. What worked for me is to place the following outside of any namespace:

    #pragma warning(disable:4483)
    void __clrcall __identifier(".cctor")() { }

  • 就是这样,您现在可以构建AnyCPU dll;由于纯"设置,它是纯 MSIL,并且由于 corflags 它将加载为 x64x86 调整.您可以在运行时避免使用任何不兼容的功能,例如 Interop.然而——这与简单地使用 /clr:safe 模式(它也产生一个 AnyCPU 库)不同——你可以使用不安全的托管指针来访问托管值类型.


    为了详细说明 Ben Voight 的评论,在这种类型的 C++/CLI AnyCPU dll 中不会工作的一件事是使用 C/C++ 初始化语法初始化非托管(即本机)、静态原语、结构体(或数组):

    That's it, you can now build the AnyCPU dll; it is pure MSIL by virtue of the 'pure' settings, and it will load either as x64 or x86 thanks to the corflags adjustment. It is up to you to avoid using any incompatible features, such as Interop, at runtime. However--and this is the difference versus just trivially using /clr:safe mode (which also produces an AnyCPU library)--you can use unsafe managed pointers to access managed value types.


    [edit:] To elaborate on Ben Voight's comment, one thing that won't work in this type of C++/CLI AnyCPU dll is the use of C/C++ initialization syntax to initialize unmanaged (i.e. native), static primitives, structs, (or arrays):

    static int my_arr[] = { 1, 2, 3 };
    

    链接器对此效果发出警告,warning LNK4210:.CRTMA 部分存在;可能存在未处理的静态初始化器或终止符.但是,您可以声明它们,自己初始化它们,然后使用它们——即获取它们的地址——并从托管代码中读取/写入它们(如果您想将这样的数组声明为 const,那么您必须为初始化程序提供空大括号 { } 并将指针转换为 volatile 以对其进行初始化.):

    The linker issues a warning to this effect, warning LNK4210: .CRTMA section exists; there may be unhandled static initializers or terminators. You can, however, declare them, initialize them yourself, and use them--that is, take their addresses--and read/write them from managed code (if you want to declare such an array as const, then you'll have to provide empty braces { } for an initializer and cast a pointer to volatile to initialize it.):

    static int my_arr[3];
    

    具有讽刺意味的是,初始化这些本地静态资源或表的一种方法是在模块构造函数或类静态构造函数期间从托管变量或资源复制它们.

    Ironically, one way to initialize these native static resources or tables is to copy them, during the module constructor or class static constructor, from a managed variable or resource.

    你问为什么要烦恼原生静态?因为无需固定即可快速访问它们.C++/CLI 在这里仍然为您做的一件好事是默默地创建一个托管值类型 (struct) 来覆盖您的每个本机静态,以便 IL 代码可以直接使用 IL 获取它们指针,从而保持程序集/pure.

    Why bother with native statics, you ask? Because they can be quickly accessed without pinning. One nice thing C++/CLI still does for you here is to silently create a managed value-type (struct) to overlay each of your native statics, so that the IL code can get at them directly with IL pointers, thus keeping the assembly /pure.

    这篇关于从 C++/CLI 项目创建纯 MSIL 程序集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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