Pedro Mota
3/1/2007 5:21:00 PM
Hi,
I made a mistake, that's why it was not working, but I didn't figured it out
at first. Just after a long debug session I saw the cause of the problem.
In fact de P/Invoke service can marshall the example that I described.
I posted an example of a more complex real situation that I have in my
current project.
The mistake was that I forgot to set the attribute MarshalAs in one the
byte[] fields saying the length of the array. It was inside a comment!!!
Problem solved. It is working on a win32 desktop environment.
But now I have another problem: it's not working on the .NET Compact
Framework.
When the P/Invoke calls the native library it throws an
OutOfMemoryException. The native method isn't called!
What are the memory constraints in the .NET Compact Framework?
"Michael Phillips, Jr." wrote:
> I have not tried to play around with your structs. I do not know why the
> marshaler is unable to understand your struct declarations.
>
> Your structs add a level of complexity with unions. You could try to
> disassemble the code to see how the "IL" disassembly is internally coding
> your structs.
>
> You could try to simply your struct declarations until you able to pinpoint
> where the compiler fails to understand how to marshal the struct.
>
> You could also change your design to use VARIANTS and SAFEARRAYS. Then your
> code will marshal without problems with all of the CLR languages.
>
> Check out my post in this newsgroup for "How to marshal complex data
> structures" for example code that may help you.
>
>
> "Pedro Mota" <PedroMota@discussions.microsoft.com> wrote in message
> news:137ED9FE-19AE-45BC-9084-17E211EE00AB@microsoft.com...
> > Thank you for your reply Michael.
> >
> > I don't understant why the default marshaler knows how to marshall when
> > the
> > fields of struct T_B and T_C are int's and does not know when the fields
> > are
> > byte[].
> > Do you know why?
> >
> > I've not to many expirience with .NET Interop, most of the work I've done
> > were relatively simple.
> >
> > I've had never done a custom marshaller and I'll have to check those
> > functions that alloc and move memory.
> >
> > I'll try to follow your aproach.
> >
> > Thanks
> > Pedro
> >
> > "Michael Phillips, Jr." wrote:
> >
> >> > This is very imporant to me and I don't know why it's not working.
> >>
> >> It is not working because the default marshaler does not know how to
> >> format
> >> the unmanaged memory that represents your structure in C.
> >>
> >> You have to help it by either creating a custom marshaler or a wrapper
> >> function that takes the memory from your managed structures and copies
> >> them
> >> exactly to the memory layout that the MyMethod method expects.
> >>
> >> It may be tedious but it can be done. You start by allocating unmanaged
> >> memory with the marshaler class to represent the layout of your C
> >> struct(i.e., T_MyStruct[] ).
> >>
> >> This chunk of memory will be held in an IntPtr and its size will be the
> >> total of 7 * sizeof(T_MyStruct).
> >>
> >> You set up a loop and use the marshal methods to move the managed memory
> >> to
> >> the unmanaged memory. You must keep track of the index into the InPtr's
> >> byte array as you are copying the structs.
> >>
> >> When you are done you pass a ref to the IntPtr to your MyMethod method.
> >>
> >>
> >> "Pedro Mota" <Pedro Mota@discussions.microsoft.com> wrote in message
> >> news:3D022598-FB2D-44F7-84C6-140084553F8E@microsoft.com...
> >> > Hello,
> >> >
> >> > I'm having the following problem and I need some help from you:
> >> >
> >> > I've a dll writen in C that has one function that has a parameter
> >> > that's
> >> > an
> >> > array of structures of type T_MyStruct.
> >> >
> >> > The structure T_MyStruct has just one field, being an array of 7
> >> > stuctures
> >> > of type T_A.
> >> >
> >> > The structure T_A has 2 fields. One is an integer and the other one is
> >> > a
> >> > union of structures (T_StructUnion).
> >> >
> >> > The union T_StructUnion is composed by 2 structures: structure T_B and
> >> > structure T_C.
> >> >
> >> > Booth structures, T_B and T_C, have one field that is a byte array of
> >> > size
> >> > 50.
> >> >
> >> >
> >> > I declared it in C# as follows:
> >> >
> >> >
> >> > [StructLayout(LayoutKind.Sequential)]
> >> > public struct T_B{
> >> >
> >> > [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
> >> > byte[] fieldB1;
> >> > }
> >> >
> >> > [StructLayout(LayoutKind.Sequential)]
> >> > public struct T_C{
> >> >
> >> > [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
> >> > byte[] fieldC1;
> >> >
> >> > }
> >> >
> >> > [StructLayout(LayoutKind.Explicit)]
> >> > public struct T_StructUnion{
> >> >
> >> > [System.Runtime.InteropServices.FieldOffset(0)]
> >> > public T_B fieldUnion1;
> >> >
> >> > [System.Runtime.InteropServices.FieldOffset(0)]
> >> > public T_C fieldUnion2;
> >> > }
> >> >
> >> >
> >> > [StructLayout(LayoutKind.Sequential)]
> >> > public struct T_A{
> >> >
> >> > public int fieldA1;
> >> >
> >> > public StructUnion fieldA2;
> >> > }
> >> >
> >> >
> >> >
> >> > [StructLayout(LayoutKind.Sequential)]
> >> > public T_MyStruct{
> >> >
> >> > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 7)]
> >> > public T_A[] myField;
> >> > }
> >> >
> >> >
> >> > [DllImport("mylib.dll", EntryPoint = "MyMethod", SetLastError = true)]
> >> > public static extern int MyMethod([In,Out] T_MyStruct[] myStructures);
> >> >
> >> >
> >> > The declaration in C languag is equivalent. The only difference is that
> >> > the
> >> > fields of structures T_B and T_C are char[100], but I declared
> >> > them as byte[] in C#. The problem is not coming from this because i've
> >> > other
> >> > structures defined like this and working good.
> >> >
> >> > The problem is that when I invoke the method I've this error written in
> >> > the
> >> > console:
> >> > "Cannot marshal field 'myField' of type 'T_MyStruct': There is no
> >> > marshaling
> >> > support for this type.
> >> > Failing when marshaling from C# to C.
> >> >
> >> > But if I declare the field in structure T_B and T_C as integers the
> >> > error
> >> > disapears, failing then internally in the DLL because the
> >> > types are not correct.
> >> >
> >> > Can someone waste some time helping me?
> >> > This is very imporant to me and I don't know why it's not working.
> >> >
> >>
> >>
> >>
>
>
>