我有一个旧的MCPP项目,它被用作在机器上运行的C ++代码和在台式计算机上运行的C#之间的通信层。最近我们决定尝试杀死这个“胶水”项目。
该项目中包含一些常用的通信列表,这些常量通常用作C ++和C#中的外部链接。
一位同事在使用以下技巧在一个地方保持对常量的更改之前是如何完成类似的事情的:
#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#编译器不要抱怨它不应该尝试编译的那一行?
答案 0 :(得分:0)
一种可能的解决方案是给C#一个名为_T
的函数(只返回它的参数),然后坚持使用原始方法:
#if !__cplusplus
public const string
#else
static const TCHAR* const
#endif
TX_TAG2xHWID_PARAMETER = _T("PR");
答案 1 :(得分:0)
一种完全不同的方法(这就是为什么它是一个单独的答案),是在构建时使用脚本生成C ++头文件和C#文件。这样,需要编辑的实际来源就像是
output_text XML_V1_TagRoot "r"
output_text TX_TAG2xHWID_PARAMETER "PR"
output_int FUNKY_INT_PARAM 43
并且凌乱的#if
都是由脚本生成的。
答案 2 :(得分:0)
您是否考虑过将字符串放入资源?这两个都可以使用符号名称从C ++或C#访问,并且字符串将存在于一个位置,并且由于字符串转义的差异而没有问题。
您还可以在构建中引入一个步骤,该步骤获取字符串及其符号名称列表并创建两个输出文件:一个用于C ++,另一个用于C#,顶部有重要注释:
// This file is machine generated. To add a constant, edit the file xxxxx
// and rebuild with the command xxxx
这至少会将所有字符串和符号名称放在一个地方,但代价是使构建过程稍微复杂化。是的,这与使用字符串资源完全相同,只是你使用的是自制工具/脚本。
答案 3 :(得分:-1)
除非您有充分的理由保持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