f_of_i | a function of 1 int variable |
---|---|
f_of_d | a function of 1 double variable |
f_of_nn | a function of 2 int parameters |
f_of_nd | a function of 1 int parameter and 1 double variable |
f_of_dd | a function of 2 double variables |
f_of_nnd | a function of 2 int parameters and 1 double variable |
f_of_ppd | a function of 2 double parameters and 1 double variable |
f_of_pppd | a function of 3 double parameters and 1 double variable |
The return values of functions are assumed to be of the double
type.
Note, that there is no difference from the point of view of function prototype between parameters and variables; the difference is in the way ACE/gr treats them - an attempt to use a vector expression as an parameter argument will result in a parse error.
Let us consider few examples.
pow(x,y)
from the Un*x math library
(libm). Of course, you can use the "^" operator defined in the ACE/gr
language, but here, for the sake of example, we want to access the function
directly.
my_function
which simply returns its (second) argument multiplied
by integer parameter transferred as the first argument.
In a text editor, type in the following C code and save it as "my_func.c":
my_func.c |
---|
double my_function (int n, double x) { double retval; retval = (double) n * x; return (retval); } |
$gcc -c -fPIC my_func.c $gcc -shared my_func.o -o /tmp/my_func.so(You may strip it to save some disk space):
$strip /tmp/my_func.soThat's all! Ready to make it visible to ACE/gr as "myf" - we are too lazy to type the very long string "my_function" many times :)
void special_func(double *input, double *output, int parameter)
.
The wrapper would look like this:
my_wrapper.c |
---|
double my_wrapper(int n, double x) { extern void special_func(double *x, double *y, int n); double retval; (void) special_func(&x, &retval, n); return (retval); } |
$gcc -c -fPIC my_wrap.c $gcc -shared my_wrap.o -o /tmp/my_wrap.so -lspecial_lib -lblas $strip /tmp/my_wrap.soNote that I added
-lblas
assuming that the special_lib library
uses some functions from the BLAS. Generally, you have to add all
libraries which your module depends on (and all libraries those libraries
rely upon etc.), as if you wanted to compile a plain executable.
myfunc.f |
---|
DOUBLE PRECISION FUNCTION MYFUNC (N, X) IMPLICIT NONE INTEGER N DOUBLE PRECISION X C MYFUNC = N * X C RETURN END |
As opposite to C, there is no way to call such a function from ACE/gr directly -
the problem is that in Fortran all arguments to a function (or subroutine) are
passed by reference. So, we need a wrapper:
myfunc_wrap.c |
---|
double myfunc_wrapper(int n, double x) { extern double myfunc_(int *, double *); double retval; retval = myfunc_(&n, &x); return (retval); } |
Note that most of f77 compilers by default add underscore to the function names
and convert all names to the lower case, hence I refer to the Fortran function
MYFUNC
from my C wrapper as myfunc_
, but in your case
it can be different!
Let us compile the whole stuff:
$g77 -c -fPIC myfunc.f $gcc -c -fPIC myfunc_wrap.c $gcc -shared myfunc.o myfunc_wrap.o -o /tmp/myfunc.so -lf2c -lm $strip /tmp/myfunc.so
And finally, inform ACE/gr about this new function: