如何元帅:
#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#中?
我试过了:
[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 typedef char T_STRING[MAX_STRING_SIZE]
答案 0 :(得分:2)
marshaller不会处理一系列固定长度的字符串。那太复杂了。
你的结构声明无论如何都是错误的。 SizeConst
指定数组长度而不是字节大小。如果您仔细考虑这一点,您将意识到您必须指定两个维度,数组长度和数组元素类型的维度。但这并不重要。没有多少调整这些属性来解决问题。
这意味着您需要手动完成。你可以使用自定义编组器来完成它。或者你可以用Marshal.AllocHGlobal
分配一块内存并传递该函数。
我无法分辨数据的流向,但这两种方式都很简单。要将数据传递给非托管代码,您需要写入分配的内存块。使用Marshal.WriteInt32
写入整数。使用Marshal.Copy
编写字符串。你需要指针算术。并且您需要使用Encoding.GetBytes
来获取字符串数据。
在相反方向,您Marshal.ReadInt32
使用uint
。并且可以将字符串复制到字节数组并使用Encoding.GetString
进行解码。
对于结构布局,您需要考虑对齐和填充。碰巧这个结构当前没有内部填充。但由于整数的对齐要求,它必须是4的倍数。扩展它时要小心。
最后,如果您同时控制托管代码和非托管代码,则可以考虑更改非托管端的数据类型,以便更轻松地进行管理。或者您可能会考虑再次使用C ++ / CLI来平滑互操作。
答案 1 :(得分:0)
使用它来通过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的大小以及字节和dword,单词以及我们今天在各种语言中没有的变量的不同而引起的,我认为C#需要知道其变量的具体位置在内存或文件中。
如果执行此操作,那么就可以为游戏或任何您自己想要的通信协议建立任何协议,请注意,将其转换为类以存储在DB中或以二进制存储在文件中非常容易,这很容易您不希望使用SQL。
亲切的问候
崩溃替代;)