有没有办法检测#pragma unmanaged是否在C ++ / CLI中生效?

时间:2011-08-12 10:58:41

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

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

在混合模式C ++ / CLI程序集中,从代码中#pragma unmanaged(或#pramga 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非托管代码块中。

3 个答案:

答案 0 :(得分:1)

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

这有点肮脏,但它会起作用。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

这是一个可行的解决方案,它利用以下事实:内部函数始终被编译为本地(非托管)代码:

#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())行。