簡體   English   中英

編組結構到單行字符串

[英]Marshaling structure to single line of string

[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
[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時,編組器始終添加一個空終止ByValTStr 因此,如果SizeConst1 ,則狀態將始終封送為空字符串。 在沒有真正看到非托管結構定義的情況下,我不會在乎告訴您如何解決此問題。

那就是我解決問題的方式:我使用了char數組和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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM