Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / March 2007

Tip: Looking for answers? Try searching our database.

Mashaling array of structures... not working I don't know why

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Pedro Mota - 26 Feb 2007 17:52 GMT
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.
Michael Phillips, Jr. - 26 Feb 2007 19:51 GMT
> 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.

> Hello,
>
[quoted text clipped - 82 lines]
> Can someone waste some time helping me?
> This is very imporant to me and I don't know why it's not working.
Pedro Mota - 27 Feb 2007 13:20 GMT
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

> > This is very imporant to me and I don't know why it's not working.
>
[quoted text clipped - 104 lines]
> > Can someone waste some time helping me?
> > This is very imporant to me and I don't know why it's not working.
Michael Phillips, Jr. - 27 Feb 2007 15:43 GMT
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.

> Thank you for your reply Michael.
>
[quoted text clipped - 132 lines]
>> > Can someone waste some time helping me?
>> > This is very imporant to me and I don't know why it's not working.
Pedro Mota - 01 Mar 2007 17:21 GMT
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?

> I have not tried to play around with your structs.  I do not know why the
> marshaler is unable to understand your struct declarations.
[quoted text clipped - 148 lines]
> >> > Can someone waste some time helping me?
> >> > This is very imporant to me and I don't know why it's not working.
Michael Phillips, Jr. - 02 Mar 2007 14:37 GMT
I have not worked with the compact framework.  I suggest that you check the
MSDN documentation for the limitations:
http://msdn2.microsoft.com/en-us/library/aa446549.aspx

> Hi,
>
[quoted text clipped - 187 lines]
>> >> > Can someone waste some time helping me?
>> >> > This is very imporant to me and I don't know why it's not working.

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.