[Mono-list] Passing structures to pinvoke

Pablo Baena pbaena@uol.com.ar
31 Mar 2003 15:40:52 +0000


--=-aYnhvDAQUjU1ys8qFTBf
Content-Type: multipart/alternative; boundary="=-8qqMy3el1oP4k21jdgjH"


--=-8qqMy3el1oP4k21jdgjH
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hello! I tried to get help in other places without much luck, so I
thought in posting here 'cause I know there're smart people in here, and
somehow is mono related :)
What I'm trying to do is to pass an object to a unmanaged routine. This
more or less works in .NET.


/* Unmanaged C */
#include <windows.h>
#include <stdlib.h>

typedef struct
{
        int i;
} test_arr_t;
 
typedef struct
{
        test_arr_t* arr;
	int nr_of_arrs;
} test_t;

__declspec (dllexport) int modify_it (test_t* testme)
{
	test_arr_t* tarr = (test_arr_t *) malloc (2 * sizeof (test_arr_t));
	/* This won't work...why oh why?
	/* testme = (test_t *) malloc ( sizeof(test_t)); */
	testme->arr = tarr;
	tarr++->i = 1;	
	tarr->i = 2;
	testme->nr_of_arrs = 2;

	return 0;
}


With the proper C# proggie:

using System;
using System.Runtime.InteropServices;

namespace teststruct
{

	[ StructLayout( LayoutKind.Sequential )]
	class test_struct_arr
	{
		public int i;
	}
	
	[ StructLayout( LayoutKind.Sequential )]
	class test_struct
	{
		public IntPtr arr;
		public int nr_of_arrs;
	}

	class Class1
	{
		[DllImport ("library")]
		static extern int modify_it ([In, Out] test_struct inta);
				
		[STAThread]
		static void Main(string[] args)
		{
			test_struct testme = new test_struct();
			modify_it (testme);
			
			test_struct_arr[] tarr = new test_struct_arr[testme.nr_of_arrs];
			IntPtr current = testme.arr;

			Console.WriteLine ("Returned object has {0} elements", testme.nr_of_arrs);

			for( int i = 0; i < testme.nr_of_arrs; i++ )
			{
				tarr[ i ] = new test_struct_arr();
				Marshal.PtrToStructure( current, tarr[ i ]);
				
				//Marshal.FreeCoTaskMem( (IntPtr)Marshal.ReadInt32( current ));
				Marshal.DestroyStructure( current, typeof(test_struct_arr) );

				current = (IntPtr)((int)current + 
					Marshal.SizeOf( tarr[ i ] ));

				Console.WriteLine ("i[{0}] = {1}", i, tarr[i].i);         
			}
		}
	}
}


But it doesn't work on mono!!! And that is where I'm aiming to. Also,
I'd rather prefer to have the parameter passed to pinvoke to be an 'out'
parameter, but it doesn't work either. These are just sample structures.
The actual structures I need to pass are a little more complicated, but
I'm trying to get these simpler ones right first.

Thank you thank you thank you!!!
-- 
Pablo Baena <pbaena@uol.com.ar>

--=-8qqMy3el1oP4k21jdgjH
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
  <META NAME="GENERATOR" CONTENT="GtkHTML/1.1.7">
</HEAD>
<BODY>
Hello! I tried to get help in other places without much luck, so I thought in posting here 'cause I know there're smart people in here, and somehow is mono related <IMG SRC="cid:1049124390.2625.55.camel@hal" ALIGN="middle" ALT=":)" BORDER="0"><BR>
What I'm trying to do is to pass an object to a unmanaged routine. This more or less works in .NET.<BR>
<BR>
<PRE>/* Unmanaged C */
#include &lt;windows.h&gt;
#include &lt;stdlib.h&gt;

typedef struct
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;
} test_arr_t;
 
typedef struct
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test_arr_t* arr;
	int nr_of_arrs;
} test_t;

__declspec (dllexport) int modify_it (test_t* testme)
{
	test_arr_t* tarr = (test_arr_t *) malloc (2 * sizeof (test_arr_t));
	/* This won't work...why oh why?
	/* testme = (test_t *) malloc ( sizeof(test_t)); */
	testme-&gt;arr = tarr;
	tarr++-&gt;i = 1;	
	tarr-&gt;i = 2;
	testme-&gt;nr_of_arrs = 2;

	return 0;
}
</PRE>
With the proper C# proggie:
<PRE>using System;
using System.Runtime.InteropServices;

namespace teststruct
{

	[ StructLayout( LayoutKind.Sequential )]
	class test_struct_arr
	{
		public int i;
	}
	
	[ StructLayout( LayoutKind.Sequential )]
	class test_struct
	{
		public IntPtr arr;
		public int nr_of_arrs;
	}

	class Class1
	{
		[DllImport (&quot;library&quot;)]
		static extern int modify_it ([In, Out] test_struct inta);
				
		[STAThread]
		static void Main(string[] args)
		{
			test_struct testme = new test_struct();
			modify_it (testme);
			
			test_struct_arr[] tarr = new test_struct_arr[testme.nr_of_arrs];
			IntPtr current = testme.arr;

			Console.WriteLine (&quot;Returned object has {0} elements&quot;, testme.nr_of_arrs);

			for( int i = 0; i &lt; testme.nr_of_arrs; i++ )
			{
				tarr[ i ] = new test_struct_arr();
				Marshal.PtrToStructure( current, tarr[ i ]);
				
				//Marshal.FreeCoTaskMem( (IntPtr)Marshal.ReadInt32( current ));
				Marshal.DestroyStructure( current, typeof(test_struct_arr) );

				current = (IntPtr)((int)current + 
					Marshal.SizeOf( tarr[ i ] ));

				Console.WriteLine (&quot;i[{0}] = {1}&quot;, i, tarr[i].i);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
			}
		}
	}
}
</PRE>
But it doesn't work on mono!!! And that is where I'm aiming to. Also, I'd rather prefer to have the parameter passed to pinvoke to be an 'out' parameter, but it doesn't work either. These are just sample structures. The actual structures I need to pass are a little more complicated, but I'm trying to get these simpler ones right first.<BR>
<BR>
Thank you thank you thank you!!!<BR>
<TABLE CELLSPACING="0" CELLPADDING="0" WIDTH="100%">
<TR>
<TD>
-- <BR>
Pablo Baena &lt;<A HREF="mailto:pbaena@uol.com.ar">pbaena@uol.com.ar</A>&gt;
</TD>
</TR>
</TABLE>

</BODY>
</HTML>

--=-8qqMy3el1oP4k21jdgjH--

--=-aYnhvDAQUjU1ys8qFTBf
Content-ID: <1049124390.2625.55.camel@hal>
Content-Disposition: attachment; filename=smiley-3.png
Content-Type: image/png; name=smiley-3.png
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC+klEQVR42n2TbUjVdxTHP/+H69Xd
a2VWlFe69rzthZJUoxeNOWoFGxEhYRRFmZSVW2u9ab2KejWE1qDNBkEQhS82VoiaZkVPmoWaKNM5
mA+opbd771//997//T/+epHBarEPHA6Hc84XDnwP/JcwcBS4AVgzcR04ONN7C+md+pcPCz44dPLA
arZs/gg1UABuGkvvp7X1Iad+itE/YtUAle8TuH26sujzqq/LkJQsnOQQVmIASVJQMhehZORiJwc5
d76FH2pf3gY2Aigzy7+eObqmtOqbXbjGGHZqCM+eQpJ9AHhWFCc5CAjWf1KAkppc+qg3vRCol4Fw
0aqcisOVW3HTE7hmBElSKD/5GFkNMhH1KDvegST78CwNSfZxeM88VuYrh4CwAuxqvxL6MnPuWiy9
H1kNUPH9fZofDKPpHn8/z+Z6Yw8JK5stX5VhRO6h+OfiV3WaHxtPVKAwmF+KqXUDMkgqZ0+UoKcE
P57/GXOqh46ODqrPXUQfufb6YOGxJOQD2CaHQnnlAJ4zDXggHBYvK6ap6Rau+RIz1k7djd+YHrqM
pXUC4KQnWTRPAdiuRqNRkFQG/omRNJOsKVQw408xtS4QDsI10AaqEY6O8Fzq70fJy3XI8gsA5HTa
rBdOkvwFKj39EWrr/sJzEnj29OvsphGugfBsLlwbZnjcYN36LxiLuADtMtCUetFAcE4ee8s+pbHV
YtOemwhHx3MSaPEY3X9OUnqsk5a2OMeP7KC3t4u+3gRALUC4cEW2eN62Q4ze3SAiz74TDxvOiI+X
BcTsoCoyfJKYn6OKmrMbxGRnlXhyJSSqv80Vq0KSAFa+ceKl0wcK9lfsW42TGsE/pxhfcDmKfz6e
FUPg4iRH6Ov6g9EJh1t341xusWuAyn9b+c7BrbklJ8oDZGTOQpL9ePY08SmDpCEwbcHwuE370yku
Nlj3gM/e90yXliyU9+8sCVJYlEUgU8IwBZruMThm83uzxsAYV4Hd/A9h4BjQBthAFOgDLgDF7w6/
ArI6YJ0eTQeGAAAAAElFTkSuQmCC

--=-aYnhvDAQUjU1ys8qFTBf--