Re: Howto use callback functions with a C DLL

Tech-Archive recommends: Fix windows errors by optimizing your registry



Jef Driesen wrote:
I have a C DLL that I want to use from a C# project. The C header file contains these declarations:

typedef void (*callback_t) (const unsigned char *data, unsigned int size, void *userdata);
void myfunction (callback_t callback, void *userdata);

How do I translate this to C#?

I tried with:

delegate void callback_t (Byte[] data, UInt32 size, IntPtr userdata);
[DllImport("mydll.dll")]
static extern void myfunction (callback_t callback, IntPtr userdata);

When calling with myfunction (null, IntPtr.Zero) everything works as expected. But once I start passing a callback function, the application crashes with "Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

void test (Byte[] data, UInt32 size, IntPtr userdata)
{
// Nothing here
}

callback_t callback = new callback_t (test);
myfunction (callback, IntPtr.Zero);

I tried changing the data parameter from a byte array to an IntPtr, but that seems to make no difference. What am I doing wrong? All other functions (without a callback function parameter) work perfect.

I think C# is somehow messing up the stack of my C DLL. If I export this very simple function in my DLL (declared as extern "C" to avoid name mangling):

typedef void (*callback_t) (const unsigned char *data, unsigned int size, void *userdata);

void
myfunction (callback_t callback, void *userdata)
{
unsigned char data[] = {'a', 'b', 'c', 0x00};
printf ("pointer=%p\n", data);
for (unsigned int i = 0; i < 5; ++i) {
printf ("iteration %u\n", i);
if (callback)
callback (NULL, sizeof (data), userdata);
printf ("pointer=%p\n", data);
}
}

And in C#, I use this code:

delegate void callback_t (IntPtr data, UInt32 size, IntPtr userdata);
[DllImport("mydll.dll")]
static extern void myfunction (callback_t callback, IntPtr userdata);

static void test (IntPtr data, UInt32 size, IntPtr userdata)
{
// Nothing here
}

Now, if I call the DLL functon in my main function with the following arguments:

myfunction1 (new callback_t (test), IntPtr.Zero);

I get this output:

pointer=0012F5F0
iteration 0
pointer=0012F5FC
iteration 1
pointer=0012F608
iteration 2
pointer=0012F614
iteration 3
pointer=0012F620
iteration 4
pointer=0012F62C

As you can see, the "data" pointer is increased by 12 bytes after each invocation of the callback function, even if this pointer was never passed to the callback function at all. If I pass "null" for the callback function, the pointer remains the same. If I do the same experiment in a C project, the pointer remains the same, just as it should be. What am I doing wrong?
.



Relevant Pages

  • Re: Howto use callback functions with a C DLL
    ... typedef void; ... static extern void myfunction (callback_t callback, ... But once I start passing a callback function, the application crashes with "Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Library design for downloading an unknown amount of data?
    ... Thus the callback function would only be called once, right before the function returns control back to the caller. ... typedef void (const unsigned char *data, unsigned int size, void *userdata); ...
    (comp.lang.c)
  • UserControl, Repeater, OnItemCommand
    ... Invalid postback or callback argument. ... protected void Page_Load ... public partial class Control_OrderItems: System.Web.UI.UserControl ...
    (microsoft.public.dotnet.csharp.general)
  • Re: function pointer help!
    ... //the return void and input prameters are defined in the manual... ... void MyProjectView::CallHandler(int,unsigned int, unsigned int, void*) ... You are attempting to use a C++ member function as the callback, but the callback is defined in terms or C, not C++. ... The underlying problem is that C++ functions receive a hidden parameter, the 'this' pointer, so their signature is incompatible with C definitions. ...
    (microsoft.public.vc.mfc)
  • Re: Guide: how to call a function
    ... When I push a button I simply want to execute a function (called ... % hObject handle to pushbutton1 ... which is _after_ your function call in your callback. ...
    (comp.soft-sys.matlab)