hreba
November 11th, 2008, 08:45 AM
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, ¶ms, 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?
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, ¶ms, 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?