OK,

I read perlguts.  I read perlapi.  I read Inline::C.  I read 
Inline::C-Cookbook.
I had the most trouble with passing the input data properly.  Eventually
everything works.

I offer the following up for inclusion in C-Cookbook to save someone else the
pain of doing this again.  There is really very little in the 
Cookbook about AV*
structures and NV*'s.

I am unclear if the newRV_noinc() macros should be newRV_inc() macros.  I used
the noinc macros because the Hash of Lists examples used them.  Does anyone
know for sure?

Scott



#!/usr/bin/perl -w

use strict;

my $n = 21;
my @angles = map {$_ * 3.1415926/($n-1)} (0..$n);
my ($cosine, $sine) = trig_wrap($n, \@angles);

for (0..$n-1) {
        print $_,"  ", $angles[$_],"  ", $$cosine[$_], "  ", $$sine[$_], "\n";
}

use Inline C => <<'END_OF_C_CODE';

/* this typically would be in a library */
void trig(int n, double * angles, double ** cosines, double ** sines)
{
        int i;
        *sines   = (double *) malloc(n*sizeof(double));
        *cosines = (double *) malloc(n*sizeof(double));

        for (i=0; i<n; i++) {
                (*cosines)[i] = cos(angles[i]);
                (*sines)[i] = sin(angles[i]);
        }
}

void trig_wrap(int n, SV* array_ref)
{
        Inline_Stack_Vars;
        double *cosine, *sine, *angles;
        AV *pcos, *psin, *av_ptr;
        SV** sv_ptr;
        int i;

/* copy values from array_ref into C array */
        angles  = (double *) malloc(n*sizeof(double));
        av_ptr = (AV*) SvRV(array_ref);
        for (i=0; i<n; i++) {
                sv_ptr = av_fetch(av_ptr,i,0);
                angles[i] = SvNV(*sv_ptr);
        }

        trig(n, angles, &cosine, &sine);

/* copy values from C arrays into perl arrays */
        pcos = newAV();
        psin = newAV();
        for (i=0; i<n; i++) {
                av_push(pcos, newSVnv(cosine[i]));
                av_push(psin, newSVnv(sine[i]  ));
        }

/* get rid of C arrays */
        free(angles);
        free(sine);
        free(cosine);

/* return references to perl arrays */
        Inline_Stack_Reset;
        Inline_Stack_Push(newRV_noinc((SV*) pcos));
        Inline_Stack_Push(newRV_noinc((SV*) psin));
        Inline_Stack_Done;
}
END_OF_C_CODE
-- 
____________________________________________________________
Scott Prahl                       http://omlc.ogi.edu/
Oregon Medical Laser Center       (503) 216-2197
9205 SW Barnes Rd                 (503) 216-2109 (secretary)
Portland OR 97225                 (503) 216-2422 (fax)

Reply via email to