C# Marshal typedef T_STRING T_STRINGS[MAX_STRING_SIZE]
本文关键字:STRING MAX SIZE STRINGS Marshal typedef | 更新日期: 2023-09-27 18:08:24
如何封送:
#define MAX_STRING_SIZE 255
typedef char T_STRING[MAX_STRING_SIZE];
#define MAX_STRING_LIST_SIZE 50
typedef T_STRING T_STRINGS[MAX_STRING_LIST_SIZE];
typedef struct
{
unsigned long m_ID;
T_STRING m_input;
T_STRINGS m_resultTexts;
} ResultList;
在c# 吗?
I have try:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ResultList
{
public uint m_ID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string m_input;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12750)]
public string[] m_resultTexts;
}
调用时抛出错误:无法封送参数#2:内部限制:结构太复杂或太大。
参数#2是ResultList结构体。
这个问题是c# Marshal typepedef char T_STRING[MAX_STRING_SIZE]
编组程序不会处理固定长度字符串的数组。这太复杂了。
你的结构声明是不正确的。SizeConst
指定数组长度,而不是字节大小。如果仔细考虑一下,就会发现必须指定两个维度,即数组长度和数组元素类型的维度。但没关系。无论如何调整这些属性都无法解决这个问题。
这意味着您需要手工操作。您可以使用自定义编组器来完成此操作。或者你可以用Marshal.AllocHGlobal
分配一块内存,然后把它传递给函数。
我不知道数据以哪种方式流动,但两种方式都很容易。要将数据传递给非托管代码,需要写入分配的内存块。使用Marshal.WriteInt32
写入整数。使用Marshal.Copy
编写字符串。您需要使用指针算术。您需要使用Encoding.GetBytes
来获取字符串数据。
在相反的方向上,您将Marshal.ReadInt32
用于uint
。并且可以将字符串复制到字节数组中,并使用Encoding.GetString
进行解码。
对于结构布局,你需要考虑对齐和填充。碰巧的是,这个结构体目前没有内部填充。但由于整数的对齐要求,它的大小必须是4的倍数。扩展的时候要小心。
最后,如果您同时控制托管和非托管代码,则可以考虑更改非托管端的数据类型,以使封送更容易。或者您可以考虑再次使用c++/CLI来平滑互操作。
使用它通过TCP/IP或PIPESTREAM发送需要做的事情如下:
在每个变量之前,就在执行MarshalAs
之后[MarshalAs(UnmanagedType.U4 or BytValArray or I4 ... ETC ]
DO: [FieldOffset(Previous offset value + Previous Variable Size in byte)]
例子 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
[FieldOffset(4)]
private char[] zSlotName;
public char[] _zSlotName
{
get { return zSlotName; }
set {
zSlotName = new char[9];
for (int i = 0; i < zSlotName.Length; i++)
{
if (value.Length > i)
zSlotName[i] = value[i];
else
zSlotName[i] = ' ';
}
}
}
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(13)]
private int nThreadId;
public int _nThreadId
{
get { return nThreadId; }
set { nThreadId = value; }
}
这将告诉编译器和程序,当你通过TCP/IP或PIPESTREAM发送变量时,或者想要将其写入二进制,在块中与其他变量相关的位置分配变量,以及如何从(STREAM)返回时读取它
我知道这听起来好像是大错特错,但这是由于不同大小的int和字节和双字,字和什么不是变量,我们必须在各种语言的一天,我认为c#需要知道它的变量在内存或文件中的具体位置。
如果你这样做,那么你应该没有任何问题,使自己的通信协议的游戏或任何你想要的,请注意,它很容易转换为类存储在DB或二进制存储在一个文件中,如果你不热衷于使用SQL。
亲切的问候