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]

C# Marshal typedef T_STRING T_STRINGS[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。

亲切的问候