2010-06-01 77 views
4

我将字节打包到一个结构中,其中一些对应于一个Unicode字符串。对于ASCII字符串以下罚款作品:什么.NET UnmanagedType是Unicode(UTF-16)?

[StructLayout(LayoutKind.Sequential)] 
private struct PacketBytes 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] 
    public string MyString; 
} 

我认为我可以做

[StructLayout(LayoutKind.Sequential)] 
private struct PacketBytes 
{ 
    [MarshalAs(UnmanagedType.LPWStr, SizeConst = 32)] 
    public string MyString; 
} 

,使之统一,但没有工作(字段值是空的,其他领域有不正确的值,表明字节拆包被搞砸了)。 (因为这个字段是其他字段的结构的一部分,所以我不能简单地改变包含结构的字符集。)

任何想法我做错了什么?

这里是输入(64个字节,小端排序):

31:00:31:00:32:00:33:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 

输出应该Unicode字符串 “1123”。

+1

你是什么意思的“没有工作”?什么失败了?顺便说一句,依靠“tstring”是一个设计问题 - 它依赖于传统的_UNICODE定义。我也相信使用UTF-16是错误的,但那是另一回事。 – 2010-06-01 17:06:26

+0

C#中没有'_UNICODE'宏,C/C++代码中的'_UNICODE'和'UNICODE'宏没有被废弃。 'TStr'仅仅意味着使用'CharSet'参数指定的编码。 – Philipp 2010-06-01 17:57:43

回答

2

我会通过声明字符串类型的嵌套结构来做到这一点。 “内部”结构可以声明它的CharSet。这类似于在我的博客解决方案:http://nitoprograms.blogspot.com/2010/02/interop-multidimensional-arrays-of.html

例如为:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct StringSizeConst32AsString 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    private string Value; 

    public static implicit operator string(StringSizeConst32AsString source) 
    { 
     return source.Value; 
    } 

    public static implicit operator StringSizeConst32AsString(string source) 
    { 
     // Note that longer strings would be silently truncated 
     // if we didn't explicitly check this. 
     if (source.Length >= 32) 
      throw new Exception("String too large for field: " + source); 

     return new StringSizeConst32AsString { Value = source }; 
    } 
} 
+0

不错!查看我的答案,了解我实施解决方案的方式。 – Pat 2010-06-01 17:38:10

0

感谢@StephenCleary。我的完整解决方案是这样的:

[StructLayout(LayoutKind.Sequential)] 
private struct PacketBytes 
{ 
    [MarshalAs(UnmanagedType.Struct)] 
    public UnicodeString MyString; 
} 

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 
private struct UnicodeString 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    public string Value; 

    public static implicit operator string(UnicodeString value) 
    { 
     return value.Value; 
    } 
} 
+0

再一次,如果有人想知道为什么我没有把CharSet放在最顶层的结构体上,那么我的实际代码中就有需要使用ASCII CharSet的结构体中的其他字段。这个解决方案可以让你同时做到 – Pat 2010-06-01 17:43:15