读书人

请问:C#的共用体运行出错的疑问

发布时间: 2012-05-06 16:15:43 作者: rapoo

请教:C#的共用体运行出错的疑问?
我定义了一个共用体。如下:

C# code
[StructLayout(LayoutKind.Explicit)]    public struct MyStruct    {        [FieldOffset(0)]        public UInt32 dwValue;        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]        [FieldOffset(0)]        public char[] s1;    }    MyStruct ms = new MyStruct(); // 运行到这里就会出错,为什么啊?                                  // 出错信息是:An unhandled exception of type 'System.TypeLoadException'                                  // occurred in System.Windows.Forms.dll而如果是把结构体的声明改为:    public struct MyStruct    {        [FieldOffset(0)]        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]        public byte[] bHigh;        [FieldOffset(64)]        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]        public byte[] bLow;        [FieldOffset(0)]        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]        public char[] s1;    }    就不会出错,这是为什么啊?    



[解决办法]
两个字段都布局到同一个内存里面去了?你这边用了字段内存布局方面的特性 感觉这个东西还是让CLR或者编译器自己去决定的比较好
[解决办法]
没有用结构体模拟过union 所以帮不上忙~
探讨

那我要怎么定义啊?可以给一个例子吗?

[解决办法]
包含引用类型和值类型的结构体,在同一个FieldOffset位置,不能声明成不同的类型
要么都是值类型,要么都是引用类型

C# code
[StructLayout(LayoutKind.Explicit)]    public struct MyStruct    {        [FieldOffset(0)]        public UInt32? dwValue;        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]        [FieldOffset(0)]        public char[] s1;    }
[解决办法]
不好意思,验证了一把,以为可空类型能解决问题,但其实不行,改成
public Object dwValue;
UINT16->Object,不会报错,但不知是否符合楼主要求
[解决办法]
LS的代码没有问题吧~
[解决办法]
报的异常是什么?我用你的代码运行了下没问题 断点去看每个成员也没问题
[解决办法]
在3.5下面编译运行也没问题 结构体声明和你一样 我这样调用尝试了下
var myStruct = new MyStruct();
myStruct.struct1 = new MyStruct1()
{
ucSelectData = new byte[1]
};
MessageBox.Show("hh");
也木有问题~
[解决办法]
关于union msdn上都有,需要声明两次
.NET Framework 开发人员指南
Unions 示例
请参见
语言筛选器: 全部 语言筛选器: 多个 语言筛选器: Visual Basic 语言筛选器: C# 语言筛选器: C++ 语言筛选器: J# 语言筛选器: JScript
Visual Basic(声明)
Visual Basic(用法)
C#
C++
J#
JScript

该示例说明如何将两种结构作为参数传递给需要联合的非托管函数,一种结构是只包含值类型的结构,一种结构是同时包含值类型和字符串的结构。联合表示一个可以由两个或多个变量共享的内存位置。Microsoft .NET Framework SDK 在 Samples\Technologies\Interop\Platform-Invoke 目录中包括此示例的完整 Visual Basic 2005 版本和 C# 版本。

Unions 示例使用以下非托管函数(这里同时显示其原始函数声明):

从 PinvokeLib.dll 导出的 TestUnion。

复制代码
void TestUnion(MYUNION u, int type);


PinvokeLib.dll 是一个自定义非托管库,它包含前面列出的函数的实现和以下两个联合:MYUNION 和 MYUNION2。这两个联合包含以下元素:

复制代码
union MYUNION
{
int number;
double d;
}

union MYUNION2
{
int i;
char str[128];
};


在托管代码中,将联合定义为结构。MyUnion 结构包含两个值类型作为其成员:一个整型和一个双精度型。StructLayoutAttribute 属性经过设置,以控制每个数据成员的准确位置。FieldOffsetAttribute 属性提供字段在联合的非托管表示形式中的物理位置。请注意,这两个成员具有相同的偏移量值,因此这两个成员可以定义相同的内存块。


MyUnion2_1 和 MyUnion2_2 分别包含一个值类型(整型)和一个字符串。在托管代码中,值类型和引用类型不允许重叠。该示例使用方法重载以使调用方能够在调用同一非托管函数时同时使用这两种类型。MyUnion2_1 的布局是显式的,并具有准确的偏移量值。与此相反,MyUnion2_2 的布局则是连续的,原因是引用类型不允许使用显式布局。MarshalAsAttribute 属性将 UnmanagedType 枚举设置为 ByValTStr,它用于标识在联合的非托管表示形式中出现的内联的定长字符数组。

LibWrap 类包含 TestUnion 和 TestUnion2 方法的原型。TestUnion2 被重载以便将 MyUnion2_1 或 MyUnion2_2 声明为参数。

声明原型
Visual Basic 复制代码
' Declares managed structures instead of unions.
< StructLayout( LayoutKind.Explicit )> _
Public Structure MyUnion
< FieldOffset( 0 )> Public i As Integer
< FieldOffset( 0 )> Public d As Double
End Structure 'MyUnion

< StructLayout( LayoutKind.Explicit, Size := 128 )> _
Public Structure MyUnion2_1
< FieldOffset( 0 )> Public i As Integer
End Structure 'MyUnion2_1

< StructLayout( LayoutKind.Sequential )> _
Public Structure MyUnion2_2
< MarshalAs( UnmanagedType.ByValTStr, SizeConst := 128 )> _
Public str As String
End Structure 'MyUnion2_2

Public Class LibWrap
' Declares managed prototypes for unmanaged function.
Declare Sub TestUnion Lib "..\LIB\PinvokeLib.dll" ( _
ByVal u As MyUnion, ByVal type As Integer )
Overloads Declare Sub TestUnion2 Lib "..\LIB\PinvokeLib.dll" ( _
ByVal u As MyUnion2_1, ByVal type As Integer )
Overloads Declare Sub TestUnion2 Lib "..\LIB\PinvokeLib.dll" ( _
ByVal u As MyUnion2_2, ByVal type As Integer )
End Class 'LibWrap


C# 复制代码
// Declares managed structures instead of unions.
[ StructLayout( LayoutKind.Explicit )]
public struct MyUnion
{
[ FieldOffset( 0 )]
public int i;
[ FieldOffset( 0 )]
public double d;
}
[ StructLayout( LayoutKind.Explicit, Size=128 )]
public struct MyUnion2_1
{
[ FieldOffset( 0 )]
public int i;
}
[ StructLayout( LayoutKind.Sequential )]
public struct MyUnion2_2
{
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String str;
}

public class LibWrap
{
// Declares managed prototypes for unmanaged function.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern void TestUnion( MyUnion u, int type );
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern void TestUnion2( MyUnion2_1 u, int type );
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern void TestUnion2( MyUnion2_2 u, int type );
}


调用函数
Visual Basic 复制代码
Public Class App
Public Shared Sub Main()
Dim mu As New MyUnion()
mu.i = 99
LibWrap.TestUnion( mu, 1 )

mu.d = 99.99
LibWrap.TestUnion( mu, 2 )

Dim mu2_1 As New MyUnion2_1()
mu2_1.i = 99
LibWrap.TestUnion2( mu2_1, 1 )

Dim mu2_2 As New MyUnion2_2()
mu2_2.str = "*** string ***"
LibWrap.TestUnion2( mu2_2, 2 )
End Sub 'Main
End Class 'App


C# 复制代码
public class App
{
public static void Main()
{
MyUnion mu = new MyUnion();
mu.i = 99;
LibWrap.TestUnion( mu, 1 );

mu.d = 99.99;
LibWrap.TestUnion( mu, 2 );

MyUnion2_1 mu2_1 = new MyUnion2_1();
mu2_1.i = 99;
LibWrap.TestUnion2( mu2_1, 1 );

MyUnion2_2 mu2_2 = new MyUnion2_2();
mu2_2.str = "*** string ***";
LibWrap.TestUnion2( mu2_2, 2 );
}
}


请参见
概念
封送类、结构和联合
平台调用数据类型
在托管代码中创建原型


要提出有关“帮助”或本产品其他功能的建议或错误报告,请转到反馈站点。

读书人网 >C#

热点推荐