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
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
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/
quien eres tú?
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!