[Mono-list] Support for Marshal.PtrToStructure in mono?

Kala B kalabalun@yahoo.co.in
Tue, 4 Jan 2005 13:48:27 +0000 (GMT)


Hi,
mono supports Marshal.PtrToStructure when the
structure  has a char[] with Charset = Unicode, but
does not support a string!! 
For example, the following works perfectly fine in
mono  without throwing any errors. 

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public class Id
{
    public int id;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst =
128)]
    public char[] name;
};

Is there any specific reason/ major difference for
mono supporting char[] with Marshal.PtrToStructure and
not adding supporting String? 

Thanks and Regards
Kala B.

 --- Kala B <kalabalun@yahoo.co.in> wrote: 
> Hi Jon,
> Thanks a lot for your reply. Sorry for the delayed
> response. Was away on vacation.
> 
> I tried my code on mono 1.1.3. With that too I get
> the
> same error:
>
-------------------------------------------------------
> ** (./mytest.exe:8693): WARNING **: marshaling
> conversion 12 not implemented
> 
> ** ERROR **: file marshal.c: line 987
> (emit_ptr_to_str_conv): should not be reached
> aborting...
> Abort
> 
>
-------------------------------------------------------
> The only difference between mono 1.0.4 ( the one I
> use) to mono 1.1.3 is that, in mono 1.0.4 I get this
> error, only when the execution path reaches the
> Marshal.PtrToStructure code path. In mono 1.1.3, the
> error is thrown the moment I run the exe.
> 
> Looks like, Marshal.PtrToStructure does not work
> when
> the structure contains a wchar_t ( Charset = Unicode
> and the string is marshalled as
> UnmanagedType.ByValTStr). I have pasted my sample
> code. When I tried the same with Charset = Ansi and
> char on the C side, everything worked fine. 
> 
> Sample code:
> ------------
> Contents of test.c
> ------------------
> 
> #include <stdio.h>
> #include <wchar.h>
> #include <assert.h>
> typedef struct _id
> {
>     int id;
> //  char name[128];
>     wchar_t name[128];
> }Id;
> 
> typedef struct _idlist
> {
>     int num;
>     Id *list;
> }IdList;
> 
> int myfunc(IdList *idList)
> {
>     printf("In lib : %s \t idList->num is
> %d\n",__func__,idList->num);
>     assert(idList->list);
>     idList->list[0].id = 10;
> //    strcpy(idList->list[0].name,"One");
>     wcscpy(idList->list[0].name,L"One");
>     idList->list[1].id = 20;
> //    strcpy(idList->list[1].name,"Two");
>     wcscpy(idList->list[1].name,L"Two");
>     idList->num = 2; 
>     return 1;
> }
> 
> Contents of chash.cs
> --------------------
> using System;
> using System.Runtime.InteropServices;
> using System.Text;
> using System.Collections.Specialized;
> 
> [StructLayout(LayoutKind.Sequential, CharSet =
> CharSet.Unicode)]
> //[StructLayout(LayoutKind.Sequential, CharSet =
> CharSet.Ansi)]
> public class Id
> {
>     public int id;
>     [MarshalAs(UnmanagedType.ByValTStr, SizeConst =
> 128)]
>     public string name;
> };
> 
> [StructLayout(LayoutKind.Sequential, CharSet =
> CharSet.Unicode)]
> //[StructLayout(LayoutKind.Sequential, CharSet =
> CharSet.Ansi)]
> 
> public class IdList
> {
>     public int num;
>     public IntPtr list;
> };
> 
> class Test
> {
>     [DllImport("libtest.so")]
>     public static extern int myfunc([In, Out] IdList
> idList);
> 
>     public static void Main()
>     {
>         Id id = new Id();
>         IdList idList = new IdList();
>         //Allocate memory for 3 ids.
>         idList.num = 3;
>         idList.list = Marshal.AllocHGlobal(3 * 
> Marshal.SizeOf(id));
> 
>         int rcode = myfunc(idList);
>         Console.WriteLine("\nmyfunc returns {0} and
> numids returned is {1} ",rcode,idList.num);
>         for (int i = 0; i< idList.num; i++)
>         {
>             IntPtr temp = new
> IntPtr(idList.list.ToInt32() + (i *
> Marshal.SizeOf(id)));
>             id = (Id)Marshal.PtrToStructure(temp,
> typeof(Id));
>             Console.WriteLine("idList[{0}] is {1}
> {2}",i,id.id,id.name);
>         }
>         Marshal.FreeHGlobal(idList.list);
> 
>     }
> }
> 
> 
> Contents of makefile
> ---------------------
> all: lib test 
> lib: testlib.c 
> 	gcc -fPIC -g -c test.c
> 	ld -x --shared -o libtest.so test.o
> test:
> 	mcs -debug chash.cs
> clean :
> 	rm ./libtest.so
> 
> 
> 
> The above sample code would anyway not print the
> correct strings because of wide character issues
> between mono and Linux wchar_t.
> 
> But MarshalAs(UnmanagedType.ByValTStr) with
> Charset=Unicode works fine if I donot use this
> structure with Marshal.PtrToStructure. ( with some
> changes for handling the wchar_t issues).
> 
> There is no difference in behaviour between mono
> 1.0.4
> and mono 1.1.3 for the sample code.
> 
> Would this be supported in mono? Is there any
> alternative solution for this problem?
> 
> Thanks in advance.
> Regards
> Kala B.
> 
> 
> 
> 
> 
> 
> 
>  
> 
> 
> 
> 
> 
>  --- Jonathan Pryor <jonpryor@vt.edu> wrote: 
> > On Thu, 2004-12-23 at 10:09 +0000, Kala B wrote:
> > > Does mono provide support for 
> > Marshal.PtrToStructure?
> > 
> > Yes, and No. :-)
> > 
> > Yes, Marshal.PtrToStructure is supported, but
> > apparently it's not
> > *fully* supported.  I imagine the nested pointer
> to
> > an array of structs
> > isn't implemented by mono's marshaller.
> > 
> > Could you create a small test case and add it to
> > bugzilla.ximian.com?
> > The bug should be added to "Mono: Runtime".
> > 
> > Also, which version of Mono are you using?  It's
> > possible that Mono
> > 1.1.3 (the development branch) has fixed this
> > problem; it might be worth
> > testing your program under it.
> > 
> > Thanks,
> 
=== message truncated === 

________________________________________________________________________
Yahoo! India Matrimony: Find your life partner online
Go to: http://yahoo.shaadi.com/india-matrimony