[英]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
。 因此,如果SizeConst
為1
,則狀態將始終封送為空字符串。 在沒有真正看到非托管結構定義的情況下,我不會在乎告訴您如何解決此問題。
那就是我解決問題的方式:我使用了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.