7

我正在开发的新 C# 程序遇到技术问题。在这个项目中,我需要与 TCP/IP 网络上的另一个非 Windows 系统进行通信。所有在其他系统上编写的软件都是用 C 完成的,任何其他未来的开发也将用 C/C++ 完成。协议全部由另一位工程师在 C 中完成,协议的定义全部使用 C typedef 结构定义所有变量并使用 memcpy 提取/放置对 C 非常有用的数据包。我所有的协议都作为 C 标头提供包含所有 typedef 和 struct 的文件以及将来对协议所做的任何更改都将以相同的方式完成。

我的问题是,是否有任何方法可以在 C# 中使用它们?

我试图将它们作为一个类编译到 DLL 库中,但由于 C# 只能使用托管 C dll,所以无法正常工作。如果我尝试编译为托管 C 类,它就会变得一团糟,因为协议中有很多数组,并且因为 C 代码必须符合一堆工厂规范,所以许多变量都是 typedef' d。现在我可以去重做 C# 中的所有结构,但这会花费很多时间,而且每次进行更改或向协议中添加某些内容时,我都必须重做。更不用说每次我这样做时都会出现错误的危险。

它与我的 C 项目的工作方式是,其他工程师只会向我提供更新的头文件。

那么有什么方法可以直接在 C# 中使用这些头文件,或者每次协议更新时我都可以进行自动转换?好吧,我基本上需要使用这个头文件从来自 TCP/IP 连接的数据流中提取数据(开始无法使用 memcpy)

使用 C# 的原因是因为我在 WPF 中使用了很多图形,而 Visual C++ 不支持 WPF

任何帮助或建议将不胜感激?

4

3 回答 3

1

我曾经不得不在 C# 中使用 C 标头来获取通过 TCP/IP 发送的编组结构的定义。我们使用的方法是通过 T4 Text Template 解析头文件。虽然这是一项有点冗长的任务,但您必须为您的标头编写足够好的 C 解析器并使用它来生成 .cs 文件,因此会有很多字符串混乱。对我们来说,这是一个足够好的解决方案,因此它也可能对您有所帮助。

在此处查看 T4:http: //msdn.microsoft.com/en-us/library/bb126445.aspx

于 2012-11-16T09:51:39.983 回答
1

不是真正的答案,更像是一种可能的好解决方案:

创建一个包含现在 C 头文件中的信息的定义文件。然后使用它来生成 .h 标头和合适的 C# 源代码。

如果数据相当简单,那么也可以使用简单的键值文件格式,甚至是 csv 文件。但如果比较复杂,那么最好使用 XML,这样更容易以编程方式解析。

如果对拥有独立于语言的定义文件有抵抗力,那么您可以尝试让 .c 头文件遵循一些字符串格式规则,这样您就可以简单地解析它并从中生成 C# 代码(只需确保编写 .h 可以理解,它不再是 C,它实际上是您自己的类 C 定义语言,任何额外的 C 内容都必须转到另一个文件)。

于 2012-11-16T09:59:52.677 回答
0

您不能也不能在 C# 中使用头文件,您需要将其编译为 dll 并从 c#

在 c 文件中,您需要定义#define DLLAPI __declspec(dllexport)和定义如下所示的方法,DLLAPI *return-value-data-type function-name* 并且从 c# 中您需要像下面这样调用它

[DllImport(@"*dll-path*")]
        public static extern *return-value-datatype function-name*

如果需要,您可以对如下数据类型进行编组

[DllImport(@"*dll-path*")]
        public static extern void InitParam([MarshalAs(UnmanagedType.LPWStr)] string inputFile,
            [MarshalAs(UnmanagedType.LPWStr)] string outputFile,
            [MarshalAs(UnmanagedType.LPWStr)] string templateFile,
            [MarshalAs(UnmanagedType.LPWStr)] string userName,
            [MarshalAs(UnmanagedType.LPWStr)] string manifestFilePath,
            [MarshalAs(UnmanagedType.LPWStr)] string usersRightList);

        [DllImport(@"*dll-path*")]
        public static extern Int32 ProtectDocument(
            [MarshalAs(UnmanagedType.LPStr)]string validToDate);

        [DllImport(@"*dll-path*")]
        public static extern void DebugGeneratedFiles(
            [MarshalAs(UnmanagedType.LPWStr)] string singedIssuenceLicenseFilePath,
            [MarshalAs(UnmanagedType.LPWStr)] string encryptedContentOutputFilePath);
于 2012-11-16T10:01:34.590 回答