Мне нужно объединить некоторые вложенные структуры в С# 4.0 в двоичные капли, чтобы перейти к платформе С++.
Я до сих пор имел большой успех, используя unsafe
/fixed
для обработки массивов фиксированной длины примитивных типов. Теперь мне нужно обработать структуру, содержащую вложенные массивы фиксированной длины других структур.
Я использовал сложные временные решения, сглаживающие структуры, но затем я наткнулся на пример атрибута MarshalAs
, который выглядел так, как будто это могло бы сэкономить мне массу проблем.
К сожалению, пока он дает мне правильное количество данных, он, похоже, также останавливает массивы fixed
от правильной сортировки, как показывает результат этой программы. Вы можете подтвердить сбой, поставив точку останова на последней строке и исследуя память на каждом указателе.
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace MarshalNested
{
public unsafe struct a_struct_test1
{
public fixed sbyte a_string[3];
public fixed sbyte some_data[12];
}
public struct a_struct_test2
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public sbyte[] a_string;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public a_nested[] some_data;
}
public unsafe struct a_struct_test3
{
public fixed sbyte a_string[3];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public a_nested[] some_data;
}
public unsafe struct a_nested
{
public fixed sbyte a_notherstring[3];
}
class Program
{
static unsafe void Main(string[] args)
{
a_struct_test1 lStruct1 = new a_struct_test1();
lStruct1.a_string[0] = (sbyte)'a';
lStruct1.a_string[1] = (sbyte)'b';
lStruct1.a_string[2] = (sbyte)'c';
a_struct_test2 lStruct2 = new a_struct_test2();
lStruct2.a_string = new sbyte[3];
lStruct2.a_string[0] = (sbyte)'a';
lStruct2.a_string[1] = (sbyte)'b';
lStruct2.a_string[2] = (sbyte)'c';
a_struct_test3 lStruct3 = new a_struct_test3();
lStruct3.a_string[0] = (sbyte)'a';
lStruct3.a_string[1] = (sbyte)'b';
lStruct3.a_string[2] = (sbyte)'c';
IntPtr lPtr1 = Marshal.AllocHGlobal(15);
Marshal.StructureToPtr(lStruct1, lPtr1, false);
IntPtr lPtr2 = Marshal.AllocHGlobal(15);
Marshal.StructureToPtr(lStruct2, lPtr2, false);
IntPtr lPtr3 = Marshal.AllocHGlobal(15);
Marshal.StructureToPtr(lStruct3, lPtr3, false);
string s1 = "";
string s2 = "";
string s3 = "";
for (int x = 0; x < 3; x++)
{
s1 += (char) Marshal.ReadByte(lPtr1+x);
s2 += (char) Marshal.ReadByte(lPtr2+x);
s3 += (char) Marshal.ReadByte(lPtr3+x);
}
Console.WriteLine("Ptr1 (size " + Marshal.SizeOf(lStruct1) + ") says " + s1);
Console.WriteLine("Ptr2 (size " + Marshal.SizeOf(lStruct2) + ") says " + s2);
Console.WriteLine("Ptr3 (size " + Marshal.SizeOf(lStruct3) + ") says " + s3);
Thread.Sleep(10000);
}
}
}
Вывод:
Ptr1 (size 15) says abc
Ptr2 (size 15) says abc
Ptr3 (size 15) says a
Поэтому по какой-то причине он только сортирует первый символ моих строк fixed
ANSI. Есть ли способ обойти это, или я сделал что-то глупое, не связанное с сортировкой?