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

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

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

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

最佳答案

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

  • 为获得最佳结果,请从托管类库项目模板中的新项目开始。将 DLL 类库的 C++/CLI 项目属性设置为 /clr:pure .这是在 Configuration Properties Visual Studio 2010 中的页面。
  • 在 C/C++ 面板上,设置 Omit Default Library NameYes /Zl
  • 对于链接器,禁用 Incremental LinkingLink Library Dependencies
  • 在链接器的“高级”页面上,我将目标机器设置为 Not Set和 CLR 图像类型为 Force Pure IL Image /CLRIMAGETYPE:PURE ,但其中一些明显的设置不被接受,因为 32BIT+ 标志仍然由 PE32 header 中的链接器设置。
  • 因此,添加 corflags步入您的构建。最好的方法是退出 Visual Studio 并使用文本编辑器编辑 vcxproj 文件。在文件底部添加:
        <!-- 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.
  • 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 };
    

    链接器为此发出警告,warning LNK4210: .CRTMA section exists; there may be unhandled static initializers or terminators .但是,您可以声明它们、自己初始化它们并使用它们——也就是说,获取它们的地址——并从托管代码中读/写它们(如果你想将这样的数组声明为 const ,那么你必须为初始化器提供空括号 { } 并将指向 volatile 的指针转换为初始化它。):
    static int my_arr[3];
    

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

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

    [编辑:更正了关于 AnyCPU 程序集中“ native ”指针的错误陈述]
    [编辑:澄清:纯汇编中的“不安全”C#代码通过IL指令(如ldloca等)使用托管指针]

    关于visual-c++ - 从 C++/CLI 项目创建纯 MSIL 程序集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6695727/

    相关文章:

    c++11 - vs 2015 pro 上没有 C++11?

    c++ - 使用循环输出框

    .net - 您可以在线程池中排队的工作项数量是否有限制?

    c# - 在异步方法中捕获异常后激活

    visual-c++ - 无法使用 VS 2013 RTM 编译 OpenCV 2.4.5

    c++ - 我正在尝试在 Visual Studio 2010 中编译 C++ 代码,但出现链接器错误

    visual-studio - VS2008 : Unit Testing with Code Coverage doesn't work with/CLR

    .net - 销毁具有静态存储持续时间的本地对象

    c++ - Silverlight 和 C++ 或 C++ 到 C# 正在进行的代码转换?

    .net - 为什么 PEVerify 说 CLR 期待静态大小数组的单维数组?