Groups | Blog | Home
all groups > dotnet interop > september 2004 >

dotnet interop : how to marshal array of structs inside a struct?


tnewton NO[at]SPAM cbnco.com
9/27/2004 7:06:13 AM
Hello,

I am trying to create a C# DLL layer for out current C dll. The
following is the current code.

(I apologize if I made any mistakes in converting it to
non-confidential. Also, I'm a complete C# newbie... )

****************************************************************

namespace MyDotNetLayer
{
public enum tRdrEnum1
{
HW = 0,
SW = 1,
};

[StructLayout(LayoutKind.Sequential)]
public struct tRdrStruct1
{
public long mask;
} ;

[StructLayout(LayoutKind.Sequential)]
public struct tRdrStruct2
{
public long plane;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=(int)5 )]
public tRdrStruct1[] s1 ;
} ;

[StructLayout(LayoutKind.Sequential)]
public struct tRdrStruct3
{
public tRdrEnum1 type;
public tRdrStruct2 s2;
} ;

public class CMyDotNetLayer
{
...

[DllImport("mydll.dll",EntryPoint="RdrFunc1")]
private static extern int oRdrFunc1(int rdr, ref tRdrStruct3
s3 ) ;
public int RdrFunc1(int rdr, ref tRdrStruct3 s3 )
{
return oRdrFunc1( rdr, ref s3 ) ;
}
}
}
****************************************************************


This is the calling code :

****************************************************************
private void Form1_Load(object sender, System.EventArgs e)
{
CMyDotNetLayer n = new CMyDotNetLayer() ;

tRdrStruct3 s3 = new tRdrStruct3() ;

s3.type = tRdrEnum1.HW ;
s3.s2.plane = 1 ;

s3.s2.s1 = new tRdrStruct1[ 5 ];
s3.s2.s1[0].mask = 1 ;

n.RdrFunc1( rdr, ref s3 ) ;

}
****************************************************************


When I call oRdrFunc1 (which should be inside the original DLL) I get
the following message box:

****************************************************************
An unhandled exception of type 'System.TypeLoadException' occurred in
MyDotNetLayer.dll

Additional information: Can not marshal field masks of type
MyDotNetLayer.tRdrStruct3: The type definition of this field has no
layout information.
****************************************************************



I've got some other stuff working, so I know I've got something right.
I'm tackling the more complicated functions first, to ensure that
this layer CAN be completed at all.

Thanks in advance,
Mattias Sjögren
9/27/2004 11:28:53 PM

[quoted text, click to view]

Keep in mind that a long in C# is 64-bits. Perhaps you should be using
an int member instead.


[quoted text, click to view]

That doesn't work, see
http://www.dotnetinterop.com/faq/?q=StructWithStructArray

In this case, if tRdrStruct1 really only has a single integer member
as declared above, I think the easiest solution is make it

[MarshalAs(UnmanagedType.ByValArray, SizeConst=5)]
public long[] s1; // or int[] ?



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
tnewton NO[at]SPAM cbnco.com
10/1/2004 7:30:20 AM
[quoted text, click to view]

I didn't know that, thanks.

[quoted text, click to view]

This worked, but there's no guarantee that that structure will ALWAYS
consist of just one int, so I'd rather implement the complete
solution.

[quoted text, click to view]

That works great. Thanks.

What about this: I have a very large byte array [1000*2000] returned
inside a structure from the DLL. The Marshal class has only a
ReadByte function, and the closest thing to memcpy I can find
(BlockCopy) doesn't work on non-Array classes. Is there a quick way
to copy a large number of bytes? (Should I start a new thread for
this question?)

Also, ReadByte in a loop gives me an exception after about 9000 calls.

Thanks again,
Mattias Sjögren
10/1/2004 11:47:50 PM
Terry,

[quoted text, click to view]

Sounds like you're looking for Marshal.Copy()



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
AddThis Social Bookmark Button