By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,887 Members | 1,148 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,887 IT Pros & Developers. It's quick & easy.

Class/struct and Marshal.SizeOf

P: n/a
SB
I feel dumb to ask because I bet this is a simple question...

Looking at the code below, can someone please explain why I get two
different values in my Marshal.SizeOf calls (see the commented lines)?

TIA!
sb
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyStruct
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyClass
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyStructTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyStruct[] dummy;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyClassTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyClass[] dummy;
}

// test code...
private void testButton_Click(object sender, EventArgs e)
{
MyStruct myStructTest = new MyStruct();
MessageBox.Show("myStructTest size: " +
Marshal.SizeOf(myStructTest).ToString());//will show size of 6

MyClass myClassTest = new MyClass();
MessageBox.Show("myClassTest size: " +
Marshal.SizeOf(myClassTest).ToString());//will show size of 6

MyStructTestClass myStructClass = new MyStructTestClass();
MessageBox.Show("myStructClass size: " +
Marshal.SizeOf(myStructClass).ToString());//will show size of 1536

MyClassTestClass myClassClass = new MyClassTestClass();
MessageBox.Show("myClass2 size: " +
Marshal.SizeOf(myClassClass).ToString());//will show size of 1024???!!
}

Nov 16 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
When I run the code I get the first 2 sizes (6 and 6), and then the
following exception...
An unhandled exception of type 'System.ArgumentException' occurred in
SizeOf.exe

Additional information: Type MyStructTestClass can not be marshaled as an
unmanaged structure; no meaningful size or offset can be computed.

Any idea's?
bobc
"SB" <st********@yahoo.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
I feel dumb to ask because I bet this is a simple question...

Looking at the code below, can someone please explain why I get two
different values in my Marshal.SizeOf calls (see the commented lines)?

TIA!
sb
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyStruct
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyClass
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyStructTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyStruct[] dummy;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyClassTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyClass[] dummy;
}

// test code...
private void testButton_Click(object sender, EventArgs e)
{
MyStruct myStructTest = new MyStruct();
MessageBox.Show("myStructTest size: " +
Marshal.SizeOf(myStructTest).ToString());//will show size of 6

MyClass myClassTest = new MyClass();
MessageBox.Show("myClassTest size: " +
Marshal.SizeOf(myClassTest).ToString());//will show size of 6

MyStructTestClass myStructClass = new MyStructTestClass();
MessageBox.Show("myStructClass size: " +
Marshal.SizeOf(myStructClass).ToString());//will show size of 1536

MyClassTestClass myClassClass = new MyClassTestClass();
MessageBox.Show("myClass2 size: " +
Marshal.SizeOf(myClassClass).ToString());//will show size of 1024???!!
}

Nov 16 '05 #2

P: n/a
SB
First, thanks for looking at the code. I'm not sure why you are getting
that error...but I will post the entire MainForm.cs file here which may
help. This compiles and runs fine on my end. Note that some changes were
made today by me but nothing substantial. One thing that may be different
on your end is that I'm using VC# Express and the .NET Framework 2.0b (link
below)...I should have mentioned that before.

http://lab.msdn.microsoft.com/expres...p/default.aspx

Anyway, I've been googling this problem ALL DAY...and I'm beginning to
believe this is a bug in the new framework. However, I'm still hoping that
someone will show me otherwise.

-sb

#region Using directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
#endregion

namespace MyTestCenter
{
partial class mainForm : Form
{
public mainForm()
{
InitializeComponent();

richTextBox.AppendText("MyStruct size: " +
Marshal.SizeOf(typeof(MyStruct)).ToString());//will show size of 6
richTextBox.AppendText("\nMyClass size: " +
Marshal.SizeOf(typeof(MyClass)).ToString());//will show size of 6
richTextBox.AppendText("\nMyStructTestClass size: " +
Marshal.SizeOf(typeof(MyStructTestClass)).ToString ());//will show size of
1536
richTextBox.AppendText("\nMyClassTestClass size: " +
Marshal.SizeOf(typeof(MyClassTestClass)).ToString( ));//will show size of
1024
}

[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)]
public struct MyStruct
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)]
public class MyClass
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)]
public class MyStructTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyStruct[] dummy;
}

[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)]
public class MyClassTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyClass[] dummy;
}
}
}
Nov 16 '05 #3

P: n/a

"SB" <st********@yahoo.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
I feel dumb to ask because I bet this is a simple question...

Looking at the code below, can someone please explain why I get two
different values in my Marshal.SizeOf calls (see the commented lines)?

TIA!
sb
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyStruct
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyClass
{
public short a;
public short b;
public short c;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyStructTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyStruct[] dummy;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MyClassTestClass
{
[MarshalAs(System.Runtime.InteropServices.Unmanaged Type.ByValArray,
SizeConst = 256)]
public MyClass[] dummy;
}

// test code...
private void testButton_Click(object sender, EventArgs e)
{
MyStruct myStructTest = new MyStruct();
MessageBox.Show("myStructTest size: " +
Marshal.SizeOf(myStructTest).ToString());//will show size of 6

MyClass myClassTest = new MyClass();
MessageBox.Show("myClassTest size: " +
Marshal.SizeOf(myClassTest).ToString());//will show size of 6

MyStructTestClass myStructClass = new MyStructTestClass();
MessageBox.Show("myStructClass size: " +
Marshal.SizeOf(myStructClass).ToString());//will show size of 1536

MyClassTestClass myClassClass = new MyClassTestClass();
MessageBox.Show("myClass2 size: " +
Marshal.SizeOf(myClassClass).ToString());//will show size of 1024???!!
}


This is not a bug, structs are value types and classes are reference types,
it is fundamental to understand the difference in layout and contents of
both.
1. A struct or class that holds an array of x elements of a value type has a
(marshaled) size of :
x * sizeof the value type, in your case: 256 * 6 = 1536.
2. A struct or a class that holds an array of x elements of a reference type
has a (marshaled) size of:
x * sizeof the reference, in your case: 256 * 4 = 1024.

It's clear that passing #1 to unmanaged code will not result in what you
expected.

This all assumes you are running the 32 bit version of the framework with
the default packing of structs.

Willy.
Note that this only works in v2.0 of the framework, and such topics should
not be posted here, better post to the whidbey NG.

Nov 16 '05 #4

P: n/a
SB
Willy,
See my notes inline:
This is not a bug, structs are value types and classes are reference
types, it is fundamental to understand the difference in layout and
contents of both.
1. A struct or class that holds an array of x elements of a value type has
a (marshaled) size of :
x * sizeof the value type, in your case: 256 * 6 = 1536.
2. A struct or a class that holds an array of x elements of a reference
type has a (marshaled) size of:
x * sizeof the reference, in your case: 256 * 4 = 1024.
I knew I was missing something obvious...now I feel dumb for not figuring
that out on my own! It makes perfect sense now.

It's clear that passing #1 to unmanaged code will not result in what you
expected.
#1 or #2? Maybe I'm misreading the above. If I understand things
correctly: it is safe for me to pass a struct which contains elements of
value types to a C dll right (assuming the correct packing)?
This all assumes you are running the 32 bit version of the framework with
the default packing of structs.
Yes, I'm using the default packing (8) so I can pass this on to a C dll.
Willy.
Note that this only works in v2.0 of the framework, and such topics should
not be posted here, better post to the whidbey NG.


Noted :)
After digesting the above, why was it necessary to have StructLayout
available for classes? In what situations would you use it for a class?

Thanks
sb
Nov 16 '05 #5

P: n/a
SB,

See inline [Willy]
Willy.

"SB" <st********@yahoo.com> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl...
Willy,
See my notes inline:
This is not a bug, structs are value types and classes are reference
types, it is fundamental to understand the difference in layout and
contents of both.
1. A struct or class that holds an array of x elements of a value type
has a (marshaled) size of :
x * sizeof the value type, in your case: 256 * 6 = 1536.
2. A struct or a class that holds an array of x elements of a reference
type has a (marshaled) size of:
x * sizeof the reference, in your case: 256 * 4 = 1024.


I knew I was missing something obvious...now I feel dumb for not figuring
that out on my own! It makes perfect sense now.

It's clear that passing #1 to unmanaged code will not result in what you
expected.


#1 or #2? Maybe I'm misreading the above. If I understand things
correctly: it is safe for me to pass a struct which contains elements of
value types to a C dll right (assuming the correct packing)?


[Willy]
#1, You can pass both a class (a) or a struct (b) containing an array of
value type (struct).

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
public short a;
public short b;
public short c;
}

a)
[StructLayout(LayoutKind.Sequential)]
public class MyStructTestClass
{
[MarshalAs(UnmanagedType.ByValArray,SizeConst = 256)]
public MyStruct[] dummy;
}

b)
[StructLayout(LayoutKind.Sequential)]
public struct MyStructTestStruct
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public MyStruct[] dummy;
}

Note however that for(b) you must pass a reference to the struct!

function(ref myStructContainsAnArrayOfStruct);

This all assumes you are running the 32 bit version of the framework with
the default packing of structs.


Yes, I'm using the default packing (8) so I can pass this on to a C dll.
Willy.
Note that this only works in v2.0 of the framework, and such topics
should not be posted here, better post to the whidbey NG.


Noted :)
After digesting the above, why was it necessary to have StructLayout
available for classes? In what situations would you use it for a class?

Thanks
sb

Nov 16 '05 #6

P: n/a
SB
Ok, I think I have it now. Thanks for the help :)

sb

"Willy Denoyette [MVP]" <wi*************@pandora.be> wrote in message
news:OG**************@TK2MSFTNGP12.phx.gbl...
SB,

See inline [Willy]
Willy.

"SB" <st********@yahoo.com> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl...
Willy,
See my notes inline:
This is not a bug, structs are value types and classes are reference
types, it is fundamental to understand the difference in layout and
contents of both.
1. A struct or class that holds an array of x elements of a value type
has a (marshaled) size of :
x * sizeof the value type, in your case: 256 * 6 = 1536.
2. A struct or a class that holds an array of x elements of a reference
type has a (marshaled) size of:
x * sizeof the reference, in your case: 256 * 4 = 1024.


I knew I was missing something obvious...now I feel dumb for not figuring
that out on my own! It makes perfect sense now.

It's clear that passing #1 to unmanaged code will not result in what you
expected.


#1 or #2? Maybe I'm misreading the above. If I understand things
correctly: it is safe for me to pass a struct which contains elements of
value types to a C dll right (assuming the correct packing)?


[Willy]
#1, You can pass both a class (a) or a struct (b) containing an array of
value type (struct).

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
public short a;
public short b;
public short c;
}

a)
[StructLayout(LayoutKind.Sequential)]
public class MyStructTestClass
{
[MarshalAs(UnmanagedType.ByValArray,SizeConst = 256)]
public MyStruct[] dummy;
}

b)
[StructLayout(LayoutKind.Sequential)]
public struct MyStructTestStruct
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public MyStruct[] dummy;
}

Note however that for(b) you must pass a reference to the struct!

function(ref myStructContainsAnArrayOfStruct);

This all assumes you are running the 32 bit version of the framework
with the default packing of structs.


Yes, I'm using the default packing (8) so I can pass this on to a C dll.
Willy.
Note that this only works in v2.0 of the framework, and such topics
should not be posted here, better post to the whidbey NG.


Noted :)
After digesting the above, why was it necessary to have StructLayout
available for classes? In what situations would you use it for a class?

Thanks
sb


Nov 16 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.