[英]Marshalling a C++ Encoded String to C#
I am trying to read in a structure that was written to a file by a C++ program (I don't have the source code).我正在尝试读取由 C++ 程序写入文件的结构(我没有源代码)。 I have been trying to read this structure into C# and marshal it so far without success.
我一直在尝试将此结构读入 C# 并将其编组,但没有成功。
The structure is basically a set of strings of fixed length, two-bytes per character.该结构基本上是一组固定长度的字符串,每个字符两个字节。 In C++, they can be declared as TCHAR[8].
在 C++ 中,它们可以声明为 TCHAR[8]。
The data on disk looks like as follows:磁盘上的数据如下所示:
I have tried the following C# code that I know can successfully read in the values as a string:我尝试了以下 C# 代码,我知道这些代码可以成功地将值作为字符串读取:
public void ReadTwoStringsOfFixedLength()
{
string field1 = string.Empty;
string field2 = string.Empty;
FileReadString(handle, out field1, 16);
FileReadString(handle, out field2, 16);
}
public static void FileReadString(BinaryReader reader, out string outVal, int length)
{
var mem = new MemoryStream();
outVal = string.Empty;
byte b = 0;
for (int i = 0; i < length; i++)
{
b = reader.ReadByte();
if (b != 0) mem.WriteByte(b);
}
outVal = Encoding.GetEncoding(1252).GetString(mem.ToArray());
}
However, what I really would like to do is use c# structs, since this data is represented as a struct in C++ (and contains other fields which I have not depicted here).但是,我真正想做的是使用 c# 结构,因为此数据在 C++ 中表示为结构(并包含我未在此处描述的其他字段)。
I have tried various methods of attempting to marshal this data based on answers I have read on StackOverflow, but none have yielded the result I wanted.我尝试了各种方法来尝试根据我在 StackOverflow 上阅读的答案来编组这些数据,但没有一个产生了我想要的结果。 In most cases, either the string encoding was incorrect, I ended up with a memory exception or I ended up with only the first character in each field (probably due to null-termination?)
在大多数情况下,要么字符串编码不正确,要么出现内存异常,要么只得到每个字段中的第一个字符(可能是由于空终止?)
Here is my code:这是我的代码:
void Main()
{
byte[] abBuffer = handle.ReadBytes(Marshal.SizeOf(typeof(MyStruct)));
//Access data
GCHandle pinnedPacket = GCHandle.Alloc(abBuffer, GCHandleType.Pinned);
var atTestStruct = (MyStruct)Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), typeof(MyStruct));
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi), Serializable]
struct MyStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
string Field1 // Resulting value = "F";
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
string Field2; // Resulting value = "F"
}
Note that I have also attempted to use CharSet.Unicode
, however the resulting strings are garbled.请注意,我也尝试使用
CharSet.Unicode
,但是结果字符串是乱码。
Any help to fix the code would be much appreciated.任何修复代码的帮助将不胜感激。
I think you need to set CharSet = CharSet.Unicode
on your StructLayout
.我认为您需要在
StructLayout
上设置CharSet = CharSet.Unicode
。
46 00 69 00
in ASCII/ANSI is considered a single character and a null terminator. ASCII/ANSI 中的
46 00 69 00
被视为单个字符和空终止符。 The documentation shows that CharSet.Unicode
is needed for two-byte characters, such as those you're showing.该文档显示两字节字符需要
CharSet.Unicode
,例如您显示的字符。
The SizeConst
value must also be the number of characters, not bytes. SizeConst
值还必须是字符数,而不是字节数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.