简体   繁体   English

将 C++ 编码的字符串编组到 C#

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM