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

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

问题描述

我尝试使用/ clr:pure和/ clrimagetype:pure flags从C ++ / CLI项目创建一个纯MSIL程序集,但是,输出程序集专门针对x86。



我缺少任何可能会阻止我的项目编译为MSIL的项目。

解决方案

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


  1. 为了获得最佳结果,从托管类库项目模板。将DLL类库的C ++ / CLI项目属性设置为 / clr:pure 。这是在Visual Studio 2010中的配置属性页面。

  2. 在C / C ++面板上,设置缺省缺省库名称到是/ Zl

  3. 对于链接器,禁用增量链接链接库依赖关系

  4. 在链接器的高级页面上,到未设置和CLR映像类型为强制纯IL映像/ CLRIMAGETYPE:PURE ,但其中一些明显设置因为32BIT +标志仍然由PE32头中的链接器设置。

  5. 因此,添加一个 corflags 步骤到你的构建。最好的方法是退出Visual Studio并使用文本编辑器编辑vcxproj文件。在文件底部,添加:

     
    <! - 在文件的底部... - >
    < Target Name =AfterBuild>
    < Exec Command =corflags $(TargetPath)/ 32BIT-/>
    < / Target>
    < / Project>

    这将运行 corflags 工具关闭DLL中的32BIT标志。确保您的路径中提供了 corflags.exe 工具。


  6. 最后,向C ++ / CLI源中添加存根文件。这是模块的静态构造函数。对我有用的是把以下的任何命名空间之外:

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


就是这样,你现在可以构建 AnyCPU dll;它是纯粹的 MSIL 凭借'纯'设置,它将加载作为 x64 x86 谢谢到 corflags 调整。在运行时,您可以避免使用任何不兼容的功能,如Interop。然而 - 这是区别对待只是平凡地使用 / clr:safe 模式(它也产生一个AnyCPU库) - 你可以使用不安全的托管指针访问托管值类型。



要详细说明Ben Voight的意见,不会在这种类型的 C ++ / CLI AnyCPU strong> dll是使用C / C ++初始化语法来初始化非托管(即原生),静态基元,结构体或数组:

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

链接器对此效果发出警告,警告LNK4210:.CRTMA节存在;可能有未处理的静态初始化程序或终止符。然而,你可以声明它们,自己初始化它们,并使用它们 - 也就是取他们的地址 - 并从托管代码读/写它们(如果你想声明一个数组 const ,那么你必须为初始化器提供空大括号 {} ,并将一个指针转换为 volatile 初始化它。):

  static int my_arr [3]讽刺的是,初始化这些本地静态资源或表的一种方法是在模块构造函数期间复制它们或者类静态构造函数。



为什么要麻烦本机静态,你问?因为它们可以快速访问而无需固定。 C ++ / CLI 在这里仍然有一个好处是静默地创建一个托管值类型(struct)来覆盖你的每个本地静态,以便IL代码可以直接用IL





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.

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

解决方案

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. 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>

    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.

  6. 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")() { }

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 };

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.

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.

[edit: corrected mis-statement regarding "native" pointers in an AnyCPU assembly] [edit: clarify: 'unsafe' C# code in pure assembly uses managed pointers via IL instructions such as ldloca, etc.]

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

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