如何确定 C++/CLI 中的当前编译目标?

How to determine current compilation target in C++/CLI?

通常,当代码由 cl.exe 使用 /clr 开关编译时,它会被 CLR 编译为 MSIL 运行。但是,完全可以使用 #pragma unmanaged 指令创建包含本机代码的混合模式程序集。

我有一些代码行,我希望它们在为 CLR 编译时和为本机平台编译时的行为有所不同。我已经检查了 this page 上的预定义预处理器宏,但遗憾的是,我无法找到一个能够在使用时判断当前代码是否正在为 MSIL 编译的宏或本机架构。我想要的基本上是

#if defined(IS_THIS_MANAGED_NOW)
#define THROW throw gcnew System::Exception("Fancy managed exception");
#else
#define THROW throw "Not-so-fancy native string";
#endif

#if defined(IS_THIS_MANAGED_NOW)
#define BSR(value, result) result = BitScanReverseManagedImpl(value)
#else
#define BSR(value, result) _BitScanReverse(&result, value);
#endif

根据当前编译目标正确工作。 (请注意,这些只是说明问题的示例,不是实时代码示例。)

编辑:

下面的程序

void print(void);

int main(int argc, char *argv[])
{
    print();

    return 0;
}

#pragma unmanaged
#include <cstdio>

void print()
{
    std::printf("__CLR_VER = %d\n", __CLR_VER);
    std::printf("__cplusplus_cli = %d\n", __cplusplus_cli);
    std::printf("_MANAGED = %d\n", _MANAGED);
}

证明如果与 /clr 一起使用,这些 #define 仍然有效,即使该函数正在为本机目标编译也是如此。

据我所知,#ifdef 不可能基于 #pragma 指令。 #ifdef 在编译的预处理器阶段处理,即编译器在后续阶段处理 #pragma 指令之前。

最接近的是使用 #ifdef __cplusplus。这取决于文件的编译方式(有或没有 /clr 标志),而不是 #pragma。根据您的项目设置方式,这可能足够精细,因为您可以在每个文件的基础上更改该设置。

#ifdef __cplusplus_cli
#define THROW throw gcnew System::Exception("Fancy managed exception");
#else
#define THROW throw "Not-so-fancy native string";
#endif

作为解决方法,您可以禁用 _MANAGED 或手动将其设置为 0 然后恢复它。


#pragma managed(push, off)
#pragma push_macro( "_MANAGED" )
#undef _MANAGED

#if defined(_MANAGED)
#define THROW throw gcnew System::Exception("Fancy managed exception");
#else
#define THROW throw "Not-so-fancy native string";
#endif

void foo()
{
    THROW;
}

#pragma pop_macro( "_MANAGED" )
#pragma managed(pop)

int main()
{
}

来源:social.msdn.microsoft.com