【问题标题】:Is there a way to detect whether #pragma unmanaged is in effect in C++/CLI?有没有办法检测 #pragma unmanaged 在 C++/CLI 中是否有效?
【发布时间】:2011-08-12 10:58:40
【问题描述】:

我有一个项目,其中包含一些对性能敏感的本机 C++ 标头,这些标头大量使用模板。对于这个项目,我们还包装了标头并添加了一些胶水代码,以将功能公开给 c# 和其他 .NET 语言。我们将此标头称为“layout.h”,并假设它是我无法更改的第三方标头。

在混合模式的 C++/CLI 程序集中,从代码中 #pragma unmanaged (或 #pragma managed(push,off) ) 的位置出现错误和 #include 相对容易。发生这种情况时,模板会生成 IL,并且在运行代码时我会获得额外的托管/非托管转换,并且性能会下降。

我的问题是是否有一种方法可以在#include 之前进行编译时检查,以便如果我不小心从错误的上下文中#include 编译失败。

// File1.cpp, compiled in a mixed mode C++/CLI assembly with /clr
    ASSERT_UNMANAGED()
    #include <layout.h>

我天真的第一次尝试检查了#ifdef _MANAGED,但无论我是否在#pragma 非托管代码块中,它总是被定义。

【问题讨论】:

  • 这真的很难。我可以想出十几种不同的方法来实现ASSERT_MANAGED,但ASSERT_UNMANAGED 让我很难过。
  • 以防万一有人查找什么,_MANAGED、__CLR_VER 和 __cplusplus_cli 不受#pragma managed/#pragma ummanaged 的​​影响,范围是整个编译单元。

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


【解决方案1】:

编译指示指令必须直接插入到包含文件中。这样,在您包含文件的任何地方都会声明一个非托管部分。

抱歉,您必须修改包含文件。

【讨论】:

    【解决方案2】:

    您可以编写ASSERT_MANAGEDASSERT_UNMANAGED 代码,这些代码将使用仅在编译托管或非托管时可用的构造。 ref class 声明是一个示例,仅在使用托管时可用。

    这有点肮脏的解决方案,但它会工作。

    【讨论】:

    • 因此,在编写 ASSERT_MANAGED() 时,引用类声明 - 确实有效。诀窍是找到合法的 C++ 而不是合法的 C++/CLI 以启用编写 ASSERT_UNMANAGED() 块
    • 另一个最接近的竞争对手是使用常量字符串连接,如果它有效,它是 CLI 代码 (System::String),否则它是本机代码。我还在探索更多!
    • 我想到了 void __fastcall foo();实际上不起作用,那里有一点编译器错误。
    • 您是否找到了 ASSERT_UNMANAGED() 的有效实现?我发现需要类似的东西......
    【解决方案3】:

    这是一个可能的解决方案,利用了内在函数总是编译为本机(非托管)代码这一事实:

    #include <intrin.h>
    
    #define ASSERT_UNMANAGED() \
    int TestFunc(void) { \
        __pragma(warning(push)) \
        __pragma(warning(error:4793)) \
        auto aumt = [] () { return _bextr_u64(65537, 0, 8); }; \
        __pragma(warning(pop)) \
        return int(aumt()); }
    
    #pragma unmanaged   // Comment out this line and the assertion fails!
    ASSERT_UNMANAGED()
    #pragma managed
    

    编辑:当然,如果您只想要警告而不是编译失败,您可以删除 3 __pragma(warning()) 行。

    【讨论】:

      猜你喜欢
      • 2018-09-15
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 2018-08-18
      • 2016-10-01
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多