[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. 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> </DIV>
<DIV>
The code below is a simplified version of what I am trying to =
accomplish.
</DIV>
<DIV> </DIV>
<DIV>
native_cb.c
</DIV>
<DIV>
#include <stdio.h>
</DIV>
<DIV>
#include <string.h>
</DIV>
<DIV> </DIV>
<DIV>
typedef int (*PasswordCallbackFunc)( char *user, char *password );
</DIV>
<DIV> </DIV>
<DIV>
PasswordCallbackFunc cbFunc =3D NULL;
</DIV>
<DIV> </DIV>
<DIV>
void SetPasswordCallbackFunction( int (*callbackFunc)(char *user, =
char *password) )
</DIV>
<DIV>
{
</DIV>
<DIV>
cbFunc =3D callbackFunc;
</DIV>
<DIV>
}
</DIV>
<DIV> </DIV>
<DIV>
void DoSomething()
</DIV>
<DIV>
{
</DIV>
<DIV>
int ccode;
</DIV>
<DIV>
char user[1024];
</DIV>
<DIV>
char passwd[1024];
</DIV>
<DIV> </DIV>
<DIV>
memset( user, 0, 1024 );
</DIV>
<DIV>
memset( passwd, 0, 1024 );
</DIV>
<DIV>
if ( cbFunc !=3D NULL )
</DIV>
<DIV>
{
</DIV>
<DIV>
ccode =3D cbFunc( user, passwd =
);
</DIV>
<DIV>
printf( "NATIVE: cbFunc =
called, returned %d\n", ccode );
</DIV>
<DIV>
printf( "NATIVE: Results:\n\=
tUser =3D %s\n\tPasswd =3D %s\n",
</DIV>
<DIV>
&nb=
sp; user, passwd );
</DIV>
<DIV>
}
</DIV>
<DIV>
else
</DIV>
<DIV>
{
</DIV>
<DIV>
printf( "NATIVE: cbFunc is =
NULL!\n" );
</DIV>
<DIV>
}
</DIV>
<DIV>
}
</DIV>
<DIV> </DIV>
<DIV>
managed_cb.cs
</DIV>
<DIV>
using System;
</DIV>
<DIV>
using System.Runtime.InteropServices;
</DIV>
<DIV> </DIV>
<DIV>
public delegate int PassWordCallback( [ MarshalAs(UnmanagedType.ByVal=
TStr, SizeConst=3D1024) ]out string user,
</DIV>
<DIV>
&nb=
sp; =
&nb=
sp; [ MarshalAs(UnmanagedType.ByValTStr, SizeConst=3D1024) ]out =
string passwd );
</DIV>
<DIV> </DIV>
<DIV>
public class Test
</DIV>
<DIV>
{
</DIV>
<DIV>
[ DllImport("native") ]
</DIV>
<DIV>
private static extern void =
SetPasswordCallbackFunction( PassWordCallback cb );
</DIV>
<DIV>
[ DllImport("native") ]
</DIV>
<DIV>
private static extern void =
DoSomething();
</DIV>
<DIV> </DIV>
<DIV>
private static int MyCallback( [ MarshalAs(Unmanage=
dType.ByValTStr, SizeConst=3D1024) ]out string user,
</DIV>
<DIV>
&nb=
sp; =
[ MarshalAs(Unm=
anagedType.ByValTStr, SizeConst=3D1024) ]out string passwd )
</DIV>
<DIV>
{
</DIV>
<DIV>
Console.WriteLine( "MANAGED:=
MyCallback called!" );
</DIV>
<DIV>
user =3D "rufas";
</DIV>
<DIV>
passwd =3D "foobar";
</DIV>
<DIV>
return 0;
</DIV>
<DIV>
}
</DIV>
<DIV> </DIV>
<DIV>
public static void Main()
</DIV>
<DIV>
{
</DIV>
<DIV>
PassWordCallback cb =3D new =
PassWordCallback( MyCallback );
</DIV>
<DIV>
SetPasswordCallbackFunction( cb =
);
</DIV>
<DIV>
Console.WriteLine( "MANAGED:=
Registered callback with native library - now forcing the library to =
invoke the callback" );
</DIV>
<DIV>
DoSomething();
</DIV>
<DIV>
Console.WriteLine( "MANAGED:=
Done...!" );
</DIV>
<DIV>
}
</DIV>
<DIV>
}
</DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV>
Running this code gives the following results:
</DIV>
<DIV>
jfehlig@jfehlig:~/temp/mono/test_code> 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>
User =3D h
</DIV>
<DIV>
Passwd =3D À=
;Ì
</DIV>
<DIV>
MANAGED: Done...!
</DIV>
<DIV> </DIV>
<DIV>
I even tried using the MarshalAs attribute on the managed MyCal=
lback method with no success.
</DIV>
<DIV>
I am certainly not the first person to attempt this. Any =
suggestions?
</DIV>
<DIV> </DIV>
<DIV>
Thanks.
</DIV>
<DIV>
Jim
</DIV>
</body>
</html>
--=__Part6B4B5033.0__=--