Преобразование структуры в одну строку строки

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class Comarea
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
    public string status;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
    public string operationName;
}

public static void StringToObject(string buffer, out Comarea comarea)
{
    IntPtr pBuf = Marshal.StringToBSTR(buffer);
    comarea = (Comarea)Marshal.PtrToStructure(pBuf, typeof(Comarea));
}

Я могу создать объект из одной строки строки, но не могу сделать наоборот.

Как я могу сделать эту операцию?

public static void ObjectToString(out string buffer, Comarea comarea)
{
     ???
}

Он выдает исключение «Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена».

int size = Marshal.SizeOf(comarea);
IntPtr pBuf = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(comarea, pBuf, false);
buffer = Marshal.PtrToStringBSTR(pBuf); //Error

person yy.celik    schedule 11.07.2014    source источник
comment
Ваша структура далеко не BSTR. BSTR имеет поле length, которое указывает длину строки. Это, конечно, отсутствует, он будет читать мусорные данные и, таким образом, вероятно, взорвется. Очень непонятно, зачем вам это нужно. Не делай этого.   -  person Hans Passant    schedule 11.07.2014


Ответы (2)


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class Comarea
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
    public string status;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
    public string operationName;
}

Он представлен в виде 6 смежных 16-битных wchar_t символьных элементов. Итак, сразу же,

public static void StringToObject(string buffer, out Comarea comarea)
{
    IntPtr pBuf = Marshal.StringToBSTR(buffer);
    comarea = (Comarea)Marshal.PtrToStructure(pBuf, typeof(Comarea));
}

неправильно. Помимо того, что вы пропускаете BSTR, ваша структура не является BSTR.

Вы можете реализовать это следующим образом:

public static void StringToObject(string buffer, out Comarea comarea)
{
    comarea.status = buffer.Substring(0, 1);
    comarea.operationName = buffer.Substring(1, 5);
}

Это при условии, что шесть символов содержат местоположения, подразумеваемые вызовами Substring.

В обратном направлении вы пишете:

public static void ObjectToString(out string buffer, Comarea comarea)
{
     buffer = comarea.status + comarea.operationName;
}

Обратите внимание, что определение структуры должно быть неправильным, однако

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
public string status;

Маршаллер всегда добавляет нуль-терминатор при использовании ByValTStr. Таким образом, с SizeConst из 1 статус всегда будет маршалироваться как пустая строка. Не видя определения неуправляемой структуры, я бы не стал рассказывать вам, как решить эту проблему.

person David Heffernan    schedule 11.07.2014

Вот как я решил свою проблему: я использовал массив символов и Marshal.PtrToStringAuto(pBuf, size)

public static void ObjectToString(out string buffer, Comarea comarea)
{
    int size = 0;
    IntPtr pBuf = IntPtr.Zero;

    try
    {
        size = Marshal.SizeOf(comarea);
        pBuf = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(comarea, pBuf, false);
        buffer = Marshal.PtrToStringAuto(pBuf, size).Substring(0, size/2); // Answer
    }
    catch
    {
        throw;
    }
    finally
    {
        Marshal.FreeHGlobal(pBuf);
    }
}





[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Comarea
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
    private char[] status;

    public string Status
    {
        get
        {
            return new string(status);
        }

        set
        {
            status = value.ToFixedCharArray(1);
        }
    }

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
    private char[] operationName;

    public string OperationName
    {
        get
        {
            return new string(operationName);
        }

        set
        {
            operationName = value.ToFixedCharArray(5);
        }
    }
}



public static class FormatterExtensions
{
    [DebuggerStepThrough]
    public static char[] ToFixedCharArray(this string inputString, int arrayLength)
    {
        char[] outputArray = new char[arrayLength];
        char[] inputArray = inputString.ToSafeTrim().ToCharArray();

        if (inputArray.Length == arrayLength)
        {
            return inputArray;
        }
        else
        {
            int i = 0;

            while (i < arrayLength)
            {
                if (i < inputArray.Length)
                {
                    outputArray[i] = inputArray[i];
                }
                else
                {
                    break;
                }

                i++;
            }

            return outputArray;
        }
    }
}

Это так полезно для связи IBM CICS (для Commarea)

person yy.celik    schedule 14.07.2014