in reply to Arrays and Inline C

For some reason, people tend to think of accessing Perl arrays from C code. I think you'll run into a lot fewer bugs if you instead deal with C arrays from Perl code, since the code is so trivial to write:

use Inline ( 'C', <<END_C ); void _munge( char *outlist, int size, char *inlist1, char *inlist2 ) { double *output = (double *) outlist; double *list1 = (double *) inlist1; double *list2 = (double *) inlist2; /* use the "arrays" just like normal for C code: */ int i; for( i= 0; i < size; ++i ) { output[i] = combine( list1[i], list2[i] ); } } END_C sub munge { my( $l1, $l2 ) = @_; my $size = 0+@$l1; my $out = "\0" x ( $size * length pack "d", 0.0 ); my $pack1 = pack "d$size", @$l1; my $pack2 = pack "d$size", @$l2; _munge( $out, $size, $pack1, $pack2 ); return unpack "d$size", $out; }

- tye        

Replies are listed 'Best First'.
Re^2: Arrays and Inline C (pack)
by ed (Initiate) on Jun 23, 2010 at 15:07 UTC
    Thanks for the example - but somehow the trick doesn't seem to work:
    use Inline 'C', <<'END_C' void _munge( char *outlist, int size, char *inlist1, char *inlist2 ) { double *output = (double *) outlist; double *list1 = (double *) inlist1; double *list2 = (double *) inlist2; int i; for( i= 0; i < size; ++i ) { printf("%f %f\n", inlist1[i], inlist2[i]); } } END_C ; my $size = 3; my $out = "\0" x ( $size * length pack "d", 0.0 ); my $pack1 = pack "d$size", 1, 2, 3; my $pack2 = pack "d$size", 4, 5, 6; _munge( $out, $size, $pack1, $pack2 );
    This prints
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
    I expected it to print the numbers passed in. What happened?

      You are passing 'char' values to your printf(), not 'double' values. Here is tested code that also includes the returning of values back to Perl:

      #!/usr/bin/perl -w use strict; use Inline 'C', <<'END_C'; void _munge( char *outbuf, int size, char *inbuf1, char *inbuf2 ) { double *output = (double *) outbuf; double *list1 = (double *) inbuf1; double *list2 = (double *) inbuf2; int i; for( i= 0; i < size; ++i ) { printf( "%f %f\n", list1[i], list2[i] ); output[i]= list1[i] * list2[i]; } } END_C my $size = 3; my $out = "\0" x ( $size * length pack "d", 0.0 ); my $pack1= pack "d$size", 1, 2, 3; my $pack2= pack "d$size", 4, 5, 6; _munge( $out, $size, $pack1, $pack2 ); print $_, $/ for unpack "d$size", $out;
      $ perl double.pl 1.000000 4.000000 2.000000 5.000000 3.000000 6.000000 4 10 18

      - tye