从C ++ / CLI项目创建纯MSIL程序集?

时间:2011-07-14 15:24:29

标签: visual-c++ c++-cli clr

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

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

2 个答案:

答案 0 :(得分:13)

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

  1. 为获得最佳结果,请从托管类库项目模板中的新项目开始。将DLL类库的C ++ / CLI项目属性设置为/clr:pure。这是在Visual Studio 2010中的Configuration Properties页面上。
  2. 在C / C ++面板上,将Omit Default Library Name设置为Yes /Zl
  3. 对于链接器,请禁用Incremental LinkingLink Library Dependencies
  4. 在链接器的“高级”页面上,我将目标计算机设置为Not Set,将CLR图像类型设置为Force Pure IL Image /CLRIMAGETYPE:PURE,但是这些显着设置中的一些不受尊重,因为32BIT +标记是仍然由PE32头中的链接器设置。
  5. 因此,请在构建中添加corflags步骤。执行此操作的最佳方法是退出Visual Studio并使用文本编辑器编辑vcxproj文件。在文件的底部,添加:
        <!-- at the bottom of the file... -->
        <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")() { }
  7. 就是这样,你现在可以构建 AnyCPU dll;由于“纯”设置,它是纯MSIL,并且由于corflags调整,它将加载为 x64 x86 。您可以在运行时避免使用任何不兼容的功能,例如Interop。但是 - 这是与使用/clr:safe模式(也产生AnyCPU库)的差别 - 你可以使用不安全的托管指针来访问托管值类型。

    <小时/> [编辑:]为了详细阐述Ben Voight的评论,在这种 C ++ / CLI AnyCPU dll中工作的一件事就是使用C / C ++初始化语法初始化非托管(即本机),静态基元,结构,(或数组):

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

    链接器会对此效果发出警告warning LNK4210: .CRTMA section exists; there may be unhandled static initializers or terminators。但是,您可以声明它们,自己初始化它们,然后使用它们 - 也就是说,获取它们的地址 - 并从托管代码中读取/写入它们(如果要将这样的数组声明为const,那么你必须为初始值设定项提供空大括号{ }并将指针强加到volatile以初始化它。):

    static int my_arr[3];
    

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

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

    [编辑:纠正了关于AnyCPU程序集中“本机”指针的错误陈述] [编辑:澄清:纯粹程序集中的'不安全'C#代码通过IL指令使用托管指针,例如ldloca等。]

答案 1 :(得分:4)

如果您使用的是Visual Studio,则应该能够在Linker下设置Target Machine项目属性 - &gt;高级设置。

如果您要查找的是将C ++ / CLI项目编译为“任何CPU”,则需要在/ clr:safe和/ clrimagetype:safe中编译。有关更多信息,请参阅以下链接:

http://bytes.com/topic/net/answers/660475-any-cpu-build-c-cli