CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12

Threaded View

  1. #1
    Join Date
    Dec 2007
    Location
    Brazil
    Posts
    37

    [RESOLVED] Interop of native C callback functions with void* parameter

    Resuming an older topic (accessing the native library GSL) which I never managed to solve, I wrote a primitive example dll (with MingW/gcc on Windows XP) just to demonstrate the problem.

    GSL (Gnu Scientific Library) contains a lot of functions (e.g.: integration routine) which require another (callback) function as argument with the prototype

    double f (double x, void *params).

    My library function example is

    double average (double (*f) (double x, void *params),
    void *par, double a, double b, int n)
    {
    int i;
    double sum, x, dx;

    sum = 0; x = a; dx = (b-a) / (n-1);
    for (i=0; i<n; i++) { sum += f(x,par); x += dx; }
    return sum / n;
    }

    I created a native dll from that and call it from a C test program which defines the actual callback function:

    double quadratic (double x, void *par)
    { double *p;
    p = par;
    return (*p * x + *(p+1)) * x + *(p+2);
    }

    and calls it with

    struct Par3 params = {1.0, 0.0, -5.0};

    printf("Average in [0,2] (10 points): %f\n",
    average (&quadratic, &params, 0.0, 2.0, 10));

    and everything works fine.

    After several tentatives to call that from .NET/CSharp, which didn't work, I came up to the following, which doesn't work either, but which is the most complete one. Delegate and dllimport are

    [StructLayout (LayoutKind.Sequential)]
    class Parameters { public double a, b, c; }

    public delegate double Func (double x, IntPtr p);

    [DllImport ("generic.dll")] public static extern
    double average (Func f, IntPtr p, double a, double b, int n);

    The actual callback function is
    public static double Quad (double x, IntPtr par)
    {
    GCHandle gch;
    Parameters p;

    gch = (GCHandle) par;
    p = (Parameters)gch.Target;
    return (p.a*x + p.b)*x + p.c;
    }

    and eveything is called like

    par = new Parameters();
    par.a = 1.0; par.b = 0.0; par.c = -5.0;
    gch = GCHandle.Alloc (par, GCHandleType.Pinned);
    func = new Func (Quad);
    avg = average (func, (IntPtr)gch, 0.0, 2.0, 10);

    which finally provokes the error message

    FatalExecutionEngineError was detected
    Message: The runtime has encountered a fatal error. The address of the error was at 0x79eb059e, on thread 0x56c. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

    The complete source code with makefile and everything is attached.
    What is wrong?
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured