将#define 从 C++ 移植到 C#
Porting #define from C++ to C#
我有一个旧的 MCPP 项目,它被用作在机器上运行的 C++ 代码和在台式计算机上运行的 C# 之间的通信层。最近我们决定尝试终止这个 "glue" 项目。
这个项目中有一些在通信中使用的常量列表,这些常量在 C++ 和 C# 中最好用作外部 link。
一位同事如何在使用以下技巧将常量更改保存在一个地方之前做过类似的事情:
#if !__cplusplus
public const string
#else
static const TCHAR* const
#endif
XML_V1_TagRoot = "r";
__cplusplus
是根据编译器设置的,所以prepeocessor 让每个编译器看到它可以编译什么。
现在我遇到了一堆 #define
类型语句的问题:
#define TX_TAG2xHWID_PARAMETER _T("PR")
其中_T()
是一个宏。所以我尝试了以下方法:
#if __cplusplus
#define TX_TAG2xHWID_PARAMETER _T("PR")
#else
internal const string TX_TAG2xHWID_PARAMETER = "PR";
#endif
这不起作用,因为 C# 没有定义值。 source
然后我尝试了:
#if __cplusplus
#define TX_TAG2xHWID_PARAMETER \
#else
internal const string TX_TAG2xHWID_PARAMETER =
#endif
#if __cplusplus
_T(\
#endif
"PR"
#if __cplusplus
)
#else
;
#endif
这里的问题是 C# 不允许多行 #define
。
基本上,问题是 #define
本身是预处理器指令,但只有在文件在 C++ 项目中编译时才应执行。
我也曾想过让 C# 项目认为它是注释,将 /*
和 */
放入不同的 #if
,但我没有成功那里。
那么,有没有人知道如何让 C# 编译器不抱怨它不应该尝试编译的那一行的解决方案?
除非您有充分的理由保留 TX_TAG2xHWID_PARAMETER 和类似的内联参数,否则您可以替换
#if __cplusplus
#define TX_TAG2xHWID_PARAMETER _T("PR")
#else
internal const string TX_TAG2xHWID_PARAMETER = "PR";
#endif
和
#if __cplusplus
LPCTSTR TX_TAG2xHWID_PARAMETER = _T("PR");
#else
internal const string TX_TAG2xHWID_PARAMETER = "PR";
#endif
一个可能的解决方案是给 C# 一个名为 _T
的函数(它只是 returns 它的参数),然后坚持原来的方法:
#if !__cplusplus
public const string
#else
static const TCHAR* const
#endif
TX_TAG2xHWID_PARAMETER = _T("PR");
一种完全不同的方法(这就是为什么它是一个单独的答案)是在构建时使用脚本生成 C++ 头文件和 C# 文件。这样,需要编辑的实际来源类似于
output_text XML_V1_TagRoot "r"
output_text TX_TAG2xHWID_PARAMETER "PR"
output_int FUNKY_INT_PARAM 43
还有那些乱七八糟的#if
都是脚本产生的
您是否考虑过将字符串放入资源中?这两个都可以使用符号名称从 C++ 或 C# 访问,并且字符串将存在于一个地方并且不会因为字符串转义的差异而出现问题。
您还可以在构建中引入一个步骤,该步骤采用字符串列表及其符号名称并创建两个输出文件:一个用于 C++,一个用于 C#,顶部有重要注释:
// This file is machine generated. To add a constant, edit the file xxxxx
// and rebuild with the command xxxx
这至少会将所有字符串和符号名称放在一个位置,代价是构建过程稍微复杂一些。是的,这与使用字符串资源完全相同,只是您使用的是 home-cooked tool/script.
我有一个旧的 MCPP 项目,它被用作在机器上运行的 C++ 代码和在台式计算机上运行的 C# 之间的通信层。最近我们决定尝试终止这个 "glue" 项目。
这个项目中有一些在通信中使用的常量列表,这些常量在 C++ 和 C# 中最好用作外部 link。
一位同事如何在使用以下技巧将常量更改保存在一个地方之前做过类似的事情:
#if !__cplusplus
public const string
#else
static const TCHAR* const
#endif
XML_V1_TagRoot = "r";
__cplusplus
是根据编译器设置的,所以prepeocessor 让每个编译器看到它可以编译什么。
现在我遇到了一堆 #define
类型语句的问题:
#define TX_TAG2xHWID_PARAMETER _T("PR")
其中_T()
是一个宏。所以我尝试了以下方法:
#if __cplusplus
#define TX_TAG2xHWID_PARAMETER _T("PR")
#else
internal const string TX_TAG2xHWID_PARAMETER = "PR";
#endif
这不起作用,因为 C# 没有定义值。 source
然后我尝试了:
#if __cplusplus
#define TX_TAG2xHWID_PARAMETER \
#else
internal const string TX_TAG2xHWID_PARAMETER =
#endif
#if __cplusplus
_T(\
#endif
"PR"
#if __cplusplus
)
#else
;
#endif
这里的问题是 C# 不允许多行 #define
。
基本上,问题是 #define
本身是预处理器指令,但只有在文件在 C++ 项目中编译时才应执行。
我也曾想过让 C# 项目认为它是注释,将 /*
和 */
放入不同的 #if
,但我没有成功那里。
那么,有没有人知道如何让 C# 编译器不抱怨它不应该尝试编译的那一行的解决方案?
除非您有充分的理由保留 TX_TAG2xHWID_PARAMETER 和类似的内联参数,否则您可以替换
#if __cplusplus
#define TX_TAG2xHWID_PARAMETER _T("PR")
#else
internal const string TX_TAG2xHWID_PARAMETER = "PR";
#endif
和
#if __cplusplus
LPCTSTR TX_TAG2xHWID_PARAMETER = _T("PR");
#else
internal const string TX_TAG2xHWID_PARAMETER = "PR";
#endif
一个可能的解决方案是给 C# 一个名为 _T
的函数(它只是 returns 它的参数),然后坚持原来的方法:
#if !__cplusplus
public const string
#else
static const TCHAR* const
#endif
TX_TAG2xHWID_PARAMETER = _T("PR");
一种完全不同的方法(这就是为什么它是一个单独的答案)是在构建时使用脚本生成 C++ 头文件和 C# 文件。这样,需要编辑的实际来源类似于
output_text XML_V1_TagRoot "r"
output_text TX_TAG2xHWID_PARAMETER "PR"
output_int FUNKY_INT_PARAM 43
还有那些乱七八糟的#if
都是脚本产生的
您是否考虑过将字符串放入资源中?这两个都可以使用符号名称从 C++ 或 C# 访问,并且字符串将存在于一个地方并且不会因为字符串转义的差异而出现问题。
您还可以在构建中引入一个步骤,该步骤采用字符串列表及其符号名称并创建两个输出文件:一个用于 C++,一个用于 C#,顶部有重要注释:
// This file is machine generated. To add a constant, edit the file xxxxx
// and rebuild with the command xxxx
这至少会将所有字符串和符号名称放在一个位置,代价是构建过程稍微复杂一些。是的,这与使用字符串资源完全相同,只是您使用的是 home-cooked tool/script.