如何确定 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()
{
}
通常,当代码由 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()
{
}