Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

marshaling fixed size array of structs

597 views
Skip to first unread message

Thomas Freudenberg

unread,
Feb 6, 2003, 7:32:24 AM2/6/03
to
Hi all,

in my C# app I have to call a function in a legacy Win32 DLL. This function
fills a complex struct. Unfortunately, I don't know how to port the data
structure to .NET. Here's a simple example:


public class Test{ [StructLayout(LayoutKind.Sequential)] public class
Test { int i; } [StructLayout(LayoutKind.Sequential)]
public class Test2 { [MarshalAs(UnmanagedType.ByValArray,
SizeConst=10)] public Test1[] tests; } public Test()
{ int size = Marshal.SizeOf(typeof(Test2)); }}In the constructor,
Marshal.SizeOf throws the exception Type Test2 can not be marshaled as an
unmanaged structure; no meaningful size or offset can be computed.

How do I marshal fixed size arrays of struct properly? I've found only this
posting http://www.dotnet247.com/247reference/msgs/28/141537.aspx, but they
do not have a solution.

Thanks in advance.

Regards
Thomas


Thomas Freudenberg

unread,
Feb 6, 2003, 7:35:47 AM2/6/03
to
Sorry, missing LFs. Here's the listing again:

public class Test
{
[StructLayout(LayoutKind.Sequential)]
public class Test
{
int i;
}

[StructLayout(LayoutKind.Sequential)]
public class Test2
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public Test1[] tests;
}

public Test()
{
int size = Marshal.SizeOf(typeof(Test2));
}
}

In the constructor, Marshal.SizeOf throws the exception Type Test2 can not
be marshaled as an unmanaged structure; no meaningful size or offset can be
computed.

Regards
Thomas


Thomas Scheidegger [MVP] NETMaster

unread,
Feb 6, 2003, 2:36:06 PM2/6/03
to
The current .NET 1.x marshaler doesn't support
struct-arrays inside a structure.

For this simple 'Test1' structure (only one 'int'), you could use:
- 'unsafe' C# and pointers.
- replace it with an int[] -array.

If you have many of this structures,
it could be easier to use Managed C++ .NET:
http://msdn.microsoft.com/vstudio/techinfo/articles/upgrade/managedext.asp
http://www.gotdotnet.com/team/cplusplus/

If you want to use the MarshalAs approach,
you have to !manually! write much code in C# like this:

// ============================= UNTESTED, USE AT YOUR OWN RISK ==============================

[StructLayout(LayoutKind.Sequential)]
public struct Test1
{
public int val1;
}

[StructLayout(LayoutKind.Sequential)]
public struct Test2
{
public int val2;
// NO Test1[10] here! => code
}

......................

Test2 head = new Test2();
Test1[] tsts = new Test1[10]; // assume 10 for this example, was 'SizeConst=10'

head.val2 = 222;
tsts[0].val1 = ....;
tsts[1].val1 = ....;
tsts[2].val1 = ....;

Type headTyp = typeof( Test2 );
int headSize = Marshal.SizeOf( Test2 );

Type tstTyp = typeof( Test1 );
int tstSize = Marshal.SizeOf( Test1 );

int memSize = headSize + tsts.Length * tstSize;
IntPtr ptr = Marshal.AllocHGlobal( memSize );

Marshal.StructureToPtr( head, ptr, false );
int run = ((int) ptr) + headSize;

int i = 0;
for( i = 0; i < tsts.Length; i++ ) // loop not needed if tsts are [Out]
{
Marshal.StructureToPtr( tsts[i], (IntPtr) run, false );
run += tstSize;
}

int r = YourUnmanagedCall(... ptr ... );


// only if it is an [Out] parameter :

head = (Test2) Marshal.PtrToStructure( ptr, headTyp );
run = ((int) ptr) + headSize;

for( i = 0; i < tsts.Length; i++ )
{
tsts[i] = (Test1) Marshal.PtrToStructure( (IntPtr) run, tstTyp );
run += tstSize;
}

Marshal.FreeHGlobal( ptr ); ptr = IntPtr.Zero;

// =========================================================================


Please check member alignment (C++: #pragma pack => ,Pack=x)

--
Thomas Scheidegger - MVP .NET - 'NETMaster'
http://www.cetus-links.org/oo_dotnet.html - http://dnetmaster.net/


Carlos Freudenberg

unread,
Apr 3, 2003, 1:31:12 PM4/3/03
to

Hola

quien eres tú?


*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!

0 new messages