4.3.1 Using PROTOTYPE
Suppose you really didn't need the feature that rtleg accepts
more than two input arguments. In that case, you can very quickly
write a C function to compute the required two argument result:
| #include <math.h>
extern void crtleg(double *r, double *x, long n);
void
crtleg(double *r, double *x, long n)
{
double y;
while (n-- > 0) {
y = *(x++) / r[0];
*(r++) *= sqrt(1. - y*y); /* result overwrites r input */
}
}
|
You can now use a PROTOTYPE comment to have codger
generate the C wrapper code to make your crtleg function
callable from interpreted code. However, you also need to write an
interpreted wrapper that will fill in the correct length n, and
ensure that the r and x arguments really do have that
length, and are conformable arrays. You do all of that in your
interface definition file, `rtleg.i', which might look like this:
| plug_in, "rtleg";
func rtleg(r, x)
{
/* convert r to double, broadcast it to result shape */
r = double(r) + array(0.0, dimsof(r, x));
/* broadcast x to result shape, blow up if not conformable */
x += 0.*r;
_crtleg, r, x, numberof(r);
return r;
}
extern _crtleg;
/* PROTOTYPE
void crtleg(double array r, double array x, long n)
*/
|
When you use this approach, your C source code makes no references at
all to yorick. It is both an advantage and a disadvantage that you
need to write an interpreted wrapper to handle all of the bookkeeping
tasks to ensure that arguments have correct types, shapes, are
conformable, and the like. The disadvantage is that you now have to
maintain both a compiled and an interpreted piece of code. The
advantage is that, as you will see in the next section, the compiled
code for consistency and conformability checks is even more tedious
than the interpreted code.