我可以在C#中使用C头作为协议吗

Can I use C headers for protocol in C#

本文关键字:协议 我可以      更新时间:2023-10-16

我在开发一个新的C#程序时遇到了技术问题。在这个项目中,我需要在TCP/IP网络上与另一个基于非windows的系统进行通信。所有在其他系统上编写的软件都是用C语言完成的,未来的任何其他开发也将用C/C++语言完成。协议都是由另一位工程师在C中完成的,协议的定义都是使用C typedef struct定义所有变量并使用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

如果有任何帮助或建议,我们将不胜感激?

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

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

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

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

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

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

您不能也不能在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);