gpt4 book ai didi

c# - 将 C header 转换为 C# - 结构内固定字符数组的 ByValArray 与 ByValTStr

转载 作者:太空宇宙 更新时间:2023-11-04 02:23:21 25 4
gpt4 key购买 nike

我有一个用 C 定义的结构:

typedef struct {
char struct_id[4];
int struct_version;
int keepAliveInterval;
……
} MQTTClient_connectOptions

我在 C# 中创建了一个相应的结构,如下所示:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MQTTClient_connectOptions {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string struct_id;
public int struct_version;
public int keepAliveInterval;
……
}

此 C# 结构是由 P/Invoke Interop Assistant 生成的,并且是我在 google 搜索中的多个帖子推荐的 C# 代码段。

定义C结构的同一个DLL/源代码也定义了函数:

DLLExport  int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options);

我在我的 C# 代码中定义为:

[DllImport("PahoMqttC", EntryPoint = "MQTTClient_connect", CharSet = CharSet.Ansi)]
public static extern int MQTTClient_connect(IntPtr handle, ref MQTTClient_connectOptions options);

在我的C#代码中,我可以设置

MQTTClient_connectOptions.struct_id = "MQTC"

当我在调试时检查对象时,我可以在该字段中看到这 4 个字符。但是,当我使用此结构调用 MQTTClient_connect() 时,“MQTC”被截断为“MQT”。

当我单步执行代码时,只要我进入 MQTTClient_connect,C# 对象检查器中的 struct_id 字段就会从“MQTC”变为“MQT\0”,并且 MQTTClient_connect 失败,因为struct_id 不是预期的。

如果我改为在 C# 中这样定义结构:

 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] struct_id;

并像这样设置它的值:

struct_id = Encoding.ASCII.GetBytes("MQTC");

然后一切正常???

我的目标是了解编码(marshal)处理和 P/Invoke 以及将 C/C++ header 转换为 C# 代码,因此我真的很想知道:

1 - 为什么在使用“string”时使用“byte[]”会导致 struct_id 的值在我进入 MQTTClient_connect() 例程时发生变化?

2 - 有没有一种方法可以使用“字符串”来定义 C# 结构,这将使我的其余 C# 代码更简单?

谢谢!

最佳答案

这样做的原因是 p/invoke 编码器必须决定 char[4] 字段是文本还是二进制(即字节)。此处的惯例是将编码为 UnmanagedType.ByValTStrstring 假定为文本。在这种情况下,它可以具有可变长度,这由必须存在的空终止符决定。这是与 char 的固定长度数组的典型用法相匹配的约定,用于保存 C 字符串。 C 字符串以 null 结尾。

但实际上,我怀疑您的数据并不是真正的文本。我怀疑该字段最好在 C 中声明为 unsigned char struct_id[4] 以指示它包含 4 个字节。不过,所有这些都有些主观,当然,我们并不认同图书馆设计背后的所有基本原理。也许有一些很好的理由将它声明为我看不到的 char 数组。

无论如何,您的 C# 代码都不能为该字段使用 string。带有 SizeConst = 4byte[] 是编码它的正确方法。记录类型上的一些辅助方法可以帮助在字节数组和字符串之间进行转换。但是,我想知道您会遇到多少不同的 ID。可能您只需要声明少量字节数组常量,您可以使用这些而不是字符串文字。

关于c# - 将 C header 转换为 C# - 结构内固定字符数组的 ByValArray 与 ByValTStr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54675274/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com