Search code examples
c#structuremarshallingunmarshallingobject-to-string

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));
}

I can create object from single line of string but I can not do opposite of that.

How can I do that operation?

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

It throws exception "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

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

Solution

  • That is how I solved my problem: I used char array and 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;
            }
        }
    }
    

    It is so useful for IBM CICS communication(For Commarea)