[Mono-list] Marshaling data from managed callback to unmanaged code

Jim Fehlig jfehlig@novell.com
Wed, 20 Oct 2004 18:43:15 -0600


This is a MIME message. If you are reading this text, you may want to 
consider changing to a mail reader or gateway that understands how to 
properly handle MIME multipart messages.

--=__Part6B4B5033.0__=
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

I'm having problems marshaling data from a managed callback to the =
calling=20
unmanaged function.  I have read Jonathan Pryor's interop doc at=20
http://www.jprl.com/~jon/interop.html and found=20
http://lists.ximian.com/archives/public/mono-list/2004-February/018214.html=
=20
in the archives but still unable to figure this one out.=20
=20
The code below is a simplified version of what I am trying to accomplish.=
=20
=20
native_cb.c=20
#include <stdio.h>=20
#include <string.h>=20
=20
typedef int (*PasswordCallbackFunc)( char *user, char *password );=20
=20
PasswordCallbackFunc cbFunc =3D NULL;=20
=20
void SetPasswordCallbackFunction( int (*callbackFunc)(char *user, char =
*password) )=20
{=20
cbFunc =3D callbackFunc;=20
}=20
=20
void DoSomething()=20
{=20
   int ccode;=20
   char user[1024];=20
   char passwd[1024];=20
=20
   memset( user, 0, 1024 );=20
   memset( passwd, 0, 1024 );=20
   if ( cbFunc !=3D NULL )=20
   {=20
      ccode =3D cbFunc( user, passwd );=20
      printf( NATIVE: cbFunc called, returned %d\n, ccode );=20
      printf( NATIVE: Results:\n\tUser =3D %s\n\tPasswd =3D %s\n,=20
              user, passwd );=20
   }=20
   else=20
   {=20
      printf( NATIVE: cbFunc is NULL!\n );=20
   }=20
}=20
=20
managed_cb.cs=20
using System;=20
using System.Runtime.InteropServices;=20
=20
public delegate int PassWordCallback( [ MarshalAs(UnmanagedType.ByValTStr, =
SizeConst=3D1024) ]out string user,=20
                                      [ MarshalAs(UnmanagedType.ByValTStr, =
SizeConst=3D1024) ]out string passwd );=20
=20
public class Test=20
{=20
   [ DllImport(native) ]=20
      private static extern void SetPasswordCallbackFunction( PassWordCallb=
ack cb );=20
   [ DllImport(native) ]=20
      private static extern void DoSomething();=20
=20
   private static int MyCallback( [ MarshalAs(UnmanagedType.ByValTStr, =
SizeConst=3D1024) ]out string user,=20
                                  [ MarshalAs(UnmanagedType.ByValTStr, =
SizeConst=3D1024) ]out string passwd )=20
   {=20
      Console.WriteLine( MANAGED: MyCallback called! );=20
      user =3D rufas;=20
      passwd =3D foobar;=20
      return 0;=20
   }=20
=20
   public static void Main()=20
   {=20
      PassWordCallback cb =3D new PassWordCallback( MyCallback );=20
      SetPasswordCallbackFunction( cb );=20
      Console.WriteLine( MANAGED: Registered callback with native library =
- now forcing the library to invoke the callback );=20
      DoSomething();=20
      Console.WriteLine( MANAGED: Done...! );=20
   }=20
}=20
=20
=20
Running this code gives the following results:=20
jfehlig@jfehlig:~/temp/mono/test_code> mono managed.exe=20
MANAGED: Registered callback with native library - now forcing the library =
to invoke the callback=20
MANAGED: MyCallback called!=20
NATIVE: cbFunc called, returned 0=20
NATIVE: Results:=20
        User =3D h=20
        Passwd =3D =C0=CC=20
MANAGED: Done...!=20
=20
I even tried using the MarshalAs attribute on the managed  MyCallback =
method with no success.=20
I am certainly not the first person to attempt this.  Any suggestions?=20
=20
Thanks.=20
Jim=20


--=__Part6B4B5033.0__=
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <style type=3D"text/css">
      <!--
        body { line-height: normal; margin-bottom: 1px; font-variant: =
normal; margin-left: 4px; margin-top: 4px; margin-right: 4px }
      -->
    </style>
   =20
  </head>
  <body>
    <DIV>
      I'm having problems marshaling data from a managed callback to the =
calling
    </DIV>
    <DIV>
      unmanaged function. &nbsp;I have read Jonathan Pryor's interop doc =
at
    </DIV>
    <DIV>
      http://www.jprl.com/~jon/interop.html and found
    </DIV>
    <DIV>
      <font color=3D"#0000ff"><a href=3D"http://lists.ximian.com/archives/p=
ublic/mono-list/2004-February/018214.html"><i><u>http://lists.ximian.com/ar=
chives/public/mono-list/2004-February/018214.html</u></i></a></font>
    </DIV>
    <DIV>
      in the archives but still unable to figure this one out.
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      The code below is a simplified version of what I am trying to =
accomplish.
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      native_cb.c
    </DIV>
    <DIV>
      #include &lt;stdio.h&gt;
    </DIV>
    <DIV>
      #include &lt;string.h&gt;
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      typedef int (*PasswordCallbackFunc)( char *user, char *password );
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      PasswordCallbackFunc cbFunc =3D NULL;
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      void SetPasswordCallbackFunction( int (*callbackFunc)(char *user, =
char *password) )
    </DIV>
    <DIV>
      {
    </DIV>
    <DIV>
      cbFunc =3D callbackFunc;
    </DIV>
    <DIV>
      }
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      void DoSomething()
    </DIV>
    <DIV>
      {
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;int ccode;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;char user[1024];
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;char passwd[1024];
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;memset( user, 0, 1024 );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;memset( passwd, 0, 1024 );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;if ( cbFunc !=3D NULL )
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ccode =3D cbFunc( user, passwd =
);
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf( &quot;NATIVE: cbFunc =
called, returned %d\n&quot;, ccode );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf( &quot;NATIVE: Results:\n\=
tUser =3D %s\n\tPasswd =3D %s\n&quot;,
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;user, passwd );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;else
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf( &quot;NATIVE: cbFunc is =
NULL!\n&quot; );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>
      }
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      managed_cb.cs
    </DIV>
    <DIV>
      using System;
    </DIV>
    <DIV>
      using System.Runtime.InteropServices;
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      public delegate int PassWordCallback( [ MarshalAs(UnmanagedType.ByVal=
TStr, SizeConst=3D1024) ]out string user,
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;[ MarshalAs(UnmanagedType.ByValTStr, SizeConst=3D1024) ]out =
string passwd );
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      public class Test
    </DIV>
    <DIV>
      {
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;[ DllImport(&quot;native&quot;) ]
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private static extern void =
SetPasswordCallbackFunction( PassWordCallback cb );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;[ DllImport(&quot;native&quot;) ]
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private static extern void =
DoSomething();
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;private static int MyCallback( [ MarshalAs(Unmanage=
dType.ByValTStr, SizeConst=3D1024) ]out string user,
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ MarshalAs(Unm=
anagedType.ByValTStr, SizeConst=3D1024) ]out string passwd )
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine( &quot;MANAGED:=
 MyCallback called!&quot; );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user =3D &quot;rufas&quot;;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;passwd =3D &quot;foobar&quot;;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;public static void Main()
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassWordCallback cb =3D new =
PassWordCallback( MyCallback );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetPasswordCallbackFunction( cb =
);
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine( &quot;MANAGED:=
 Registered callback with native library - now forcing the library to =
invoke the callback&quot; );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoSomething();
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine( &quot;MANAGED:=
 Done...!&quot; );
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>
      }
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      Running this code gives the following results:
    </DIV>
    <DIV>
      jfehlig@jfehlig:~/temp/mono/test_code&gt; mono managed.exe
    </DIV>
    <DIV>
      MANAGED: Registered callback with native library - now forcing the =
library to invoke the callback
    </DIV>
    <DIV>
      MANAGED: MyCallback called!
    </DIV>
    <DIV>
      NATIVE: cbFunc called, returned 0
    </DIV>
    <DIV>
      NATIVE: Results:
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User =3D h
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Passwd =3D&nbsp;&#192=
;&#204;
    </DIV>
    <DIV>
      MANAGED: Done...!
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      I even tried using the MarshalAs attribute on the managed &nbsp;MyCal=
lback method with no success.
    </DIV>
    <DIV>
      I am certainly not the first person to attempt this. &nbsp;Any =
suggestions?
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      Thanks.
    </DIV>
    <DIV>
      Jim
    </DIV>
  </body>
</html>

--=__Part6B4B5033.0__=--