Given the following C function from a library I want to link to:
typedef void (*fptr_f) (double, double *, double *, void *);
void foo(_fptr_f f, double *y, void *_data);
I have written the following Nim equivalent:
type fptr_f = proc(t: cdouble, y: ptr cdouble, ydot: ptr cdouble, data: pointer): void {.cdecl.}
proc foo(f: fptr_f, y: ptr cdouble, data: pointer): void {.importc: "lsoda".}
How do I write the following C function in Nim and pass it to the proc foo in Nim?
static void fex(double t, double *y, double *ydot, void *data)
{
ydot[0] = 1.0E4 * y[1] * y[2] - .04E0 * y[0];
ydot[2] = 3.0E7 * y[1] * y[1];
ydot[1] = -1.0 * (ydot[0] + ydot[2]);
}
If pointer type points to an array, ptr UncheckedArray[cdouble] (or ptr array[3, cdouble] if array size is fixed) is better than ptr cdouble.
Example runnable code:
import std/strformat
{.emit:"""
typedef void (*fptr_f) (double, double *, double *, void *);
void foo(fptr_f f, double *y, void *_data);
void foo(fptr_f f, double *y, void *_data) {
double ydot[3];
f(123.0, y, ydot, _data);
printf("In C function\n");
printf("ydot = [%f, %f, %f]\n", ydot[0], ydot[1], ydot[2]);
}
""".}
type fptr_f = proc(t: cdouble; y: ptr UncheckedArray[cdouble]; ydot: ptr UncheckedArray[cdouble]; data: pointer) {.cdecl.}
proc foo(f: fptr_f; y: ptr UncheckedArray[cdouble]; data: pointer): void {.importc: "foo".}
proc nimCallback(t: cdouble; y: ptr UncheckedArray[cdouble]; ydot: ptr UncheckedArray[cdouble]; data: pointer) {.cdecl.} =
echo "In nimCallback"
echo &"t = {t}"
echo &"y = [{y[0]}, {y[1]}, {y[2]}]"
for i in 0..2:
ydot[i] = y[i]
var y = [cdouble 1.0, 2.0, 3.0];
foo(nimCallback, cast[ptr UncheckedArray[cdouble]](y[0].addr), nil)
Can I ask another question relating to double pointers.
Given the following C function:
int calc_jac(double y[], double** jac)
{
double r = 6.0e7 * y[0];
jac[1][0] = r;
jac[0][0] = -0.04 - 1.0e4 * y[1] - r
jac[0][1] = -0.04 - 1.0e4 * y[0]
jac[1][1] = 0.0
return 1
}
My Nim equivalent for the declaration is:
proc calcJac(y: ptr UncheckedArray[cdouble], jacobian: ptr UncheckedArray[ptr cdouble])