Groups | Blog | Home
all groups > dotnet interop > february 2006 >

dotnet interop : P/Invoke of CallBack with char* params: return error


Lionel Reyero
2/14/2006 1:13:26 PM

Hi there,

I am trying to P/Invoke a DLL able to perform a wifi scan.

There is a poll method to which I have to pass a pointer to a function. Then
the native code will call back the passed function which has char* parameters.

I tried to write my P/Invoke (see below) but when I run the application, I
get an exception when the "poll" method is called. The exception has the
following message: Attempted to read or write protected memory. This is often
an indication that other memory is corrupt.

As far as I read, I am not sure that my "delegate" is correct. I am also
unsure about how I should translate the "char *" in C#.

Your help (and code snipets) will be greatly appreciated! Thanks a lot!

Lionel Reyero

==========================
Here is the .h I want to P/Invoke


#ifndef __COMMON_SPOTTER_H__
#define __COMMON_SPOTTER_H__


typedef void (*SawAPFunction)(char *bssid, char *ssid, int rss,int wep,int
infrMode);

/* returns 0 on success, -1 on failure */
int spotter_init();

void spotter_shutdown();

/* returns 0 on success, -1 on failure */
int spotter_poll(SawAPFunction fn);


#endif /* __COMMON_SPOTTER_H__ */


===============================
Here is the P/Invoke I have done:

public delegate void CallBack(IntPtr bssid, IntPtr ssid, int rss, int
wep, int infrMode);


class Spotter
{

[DllImport("spotter.dll",
EntryPoint="_Java_org_placelab_spotter_WiFiSpotter_spotter_1init@8")]
public static extern int init();

[DllImport("spotter.dll", EntryPoint =
"_Java_org_placelab_spotter_WiFiSpotter_spotter_1shutdown@8")]
public static extern void shutdown();

[DllImport("spotter.dll", EntryPoint =
"_Java_org_placelab_spotter_WiFiSpotter_spotter_1poll@8")]
public static extern int poll(CallBack x);

public static void AP_detected(IntPtr bssid, IntPtr ssid, int rss,
int wep, int infrMode)
{

}
Robert Simpson
2/14/2006 8:01:56 PM
Without seriously tweaking the compiled runtime, you cannot have cdecl
callbacks in .NET. The declaration as you've made it:

[quoted text, click to view]

.... is cdecl and not stdcall. At best, your function will be called one
time and then you'll get a popup error afterwards saying something about the
value of ESP not being preserved or something. You'll likely get a GP fault
instead. The *outgoing* cdecl api calls you've declared aren't
showstoppers, since .NET can detect the stack mismatch and correct it ...
but aside from running ILDASM on your compiled app, tweaking the callback to
make it cdecl and recompiling with ILASM, you can't have a cdecl *incoming*
callback.

Robert

[quoted text, click to view]

Willy Denoyette [MVP]
2/15/2006 12:00:00 AM
While this is true for v1 of the framework, it's no longer the case with v2.
Now, you can specify alternate calling conventions for "delegated"
callbacks.

Willy.

[quoted text, click to view]
| Without seriously tweaking the compiled runtime, you cannot have cdecl
| callbacks in .NET. The declaration as you've made it:
|
| > typedef void (*SawAPFunction)(char *bssid, char *ssid, int rss,int
wep,int
| > infrMode);
|
| ... is cdecl and not stdcall. At best, your function will be called one
| time and then you'll get a popup error afterwards saying something about
the
| value of ESP not being preserved or something. You'll likely get a GP
fault
| instead. The *outgoing* cdecl api calls you've declared aren't
| showstoppers, since .NET can detect the stack mismatch and correct it ...
| but aside from running ILDASM on your compiled app, tweaking the callback
to
| make it cdecl and recompiling with ILASM, you can't have a cdecl
*incoming*
| callback.
|
| Robert
|
[quoted text, click to view]
| >
| > Hi there,
| >
| > I am trying to P/Invoke a DLL able to perform a wifi scan.
| >
| > There is a poll method to which I have to pass a pointer to a function.
| > Then
| > the native code will call back the passed function which has char*
| > parameters.
| >
| > I tried to write my P/Invoke (see below) but when I run the application,
I
| > get an exception when the "poll" method is called. The exception has the
| > following message: Attempted to read or write protected memory. This is
| > often
| > an indication that other memory is corrupt.
| >
| > As far as I read, I am not sure that my "delegate" is correct. I am also
| > unsure about how I should translate the "char *" in C#.
| >
| > Your help (and code snipets) will be greatly appreciated! Thanks a lot!
| >
| > Lionel Reyero
| >
| > ==========================
| > Here is the .h I want to P/Invoke
| >
| >
| > #ifndef __COMMON_SPOTTER_H__
| > #define __COMMON_SPOTTER_H__
| >
| >
| > typedef void (*SawAPFunction)(char *bssid, char *ssid, int rss,int
wep,int
| > infrMode);
| >
| > /* returns 0 on success, -1 on failure */
| > int spotter_init();
| >
| > void spotter_shutdown();
| >
| > /* returns 0 on success, -1 on failure */
| > int spotter_poll(SawAPFunction fn);
| >
| >
| > #endif /* __COMMON_SPOTTER_H__ */
| >
| >
| > ===============================
| > Here is the P/Invoke I have done:
| >
| > public delegate void CallBack(IntPtr bssid, IntPtr ssid, int rss, int
| > wep, int infrMode);
| >
| >
| > class Spotter
| > {
| >
| > [DllImport("spotter.dll",
| > EntryPoint="_Java_org_placelab_spotter_WiFiSpotter_spotter_1init@8")]
| > public static extern int init();
| >
| > [DllImport("spotter.dll", EntryPoint =
| > "_Java_org_placelab_spotter_WiFiSpotter_spotter_1shutdown@8")]
| > public static extern void shutdown();
| >
| > [DllImport("spotter.dll", EntryPoint =
| > "_Java_org_placelab_spotter_WiFiSpotter_spotter_1poll@8")]
| > public static extern int poll(CallBack x);
| >
| > public static void AP_detected(IntPtr bssid, IntPtr ssid, int
rss,
| > int wep, int infrMode)
| > {
| >
| > }
| > }
|
|

Robert Simpson
2/15/2006 8:25:57 AM
Have a code sample? I can't find information on this in the MSDN docs ...

[quoted text, click to view]


Willy Denoyette [MVP]
2/15/2006 9:21:53 PM

[quoted text, click to view]
| Have a code sample? I can't find information on this in the MSDN docs ...
|
[quoted text, click to view]
| > While this is true for v1 of the framework, it's no longer the case with
| > v2.
| > Now, you can specify alternate calling conventions for "delegated"
| > callbacks.
| >
| > Willy.
|
|
|


Search for "UnmanagedFunctionPointerAttribute "in the docs, this attribute
can be applied to a delegate like:

[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate bool CallBack(........);

another new method is GetFunctionPointerForDelegate which converts a
delegate to an IntPtr that can be passed to unmanaged code as a managed
function pointer.

Willy.


AddThis Social Bookmark Button