Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

perlxs and gcc error

by Anonymous Monk
on Feb 11, 2003 at 12:18 UTC ( #234367=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to make a c command for use in perl with perlxs. However there is an error in "make" and I can't seem to be able to fix it.

I'm makin command "do_pearson_matrix(\@in_table,$max_i,$max_j)", which should then return the new 2-d array. The $max_i and $max_j has information about the lenghts of my 2-d array (@in_table).

Error code:

$ make /usr/bin/perl -I/usr/lib/perl5/5.6.1/i386-linux -I/usr/lib/perl5/5.6.1 + /usr/lib/perl5/5.6.1/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.6.1/ +ExtUtils/typemap test_c.xs > test_c.xsc && mv test_c.xsc test_c.c gcc -c -fno-strict-aliasing -I/usr/local/include -O2 -march=i386 -mcp +u=i686 -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" -fPIC -I/usr/lib/pe +rl5/5.6.1/i386-linux/CORE test_c.c test_c.xs: In function `XS_test_c_do_matrix': test_c.xs:19: subscripted value is neither array nor pointer test_c.xs:19: subscripted value is neither array nor pointer make: *** [test_c.o] Error 1

And the .xs file:

#include "EXTERN.h" #include "perl.h" #include "XSUB.h" MODULE = test_c PACKAGE = test_c double do_matrix (double &in_matrix,long max_i,long max_j,OUTLIST out_matrix[ +i][j]) PROTOTYPE: \@$$ CODE: long i,j,a; double value,out_matrix[i][j]; for (i=0;i<=max_i;i++) { for (j=(i-1);j>=0;j--) { value=0; for (a=0;a<=max_j;a++) { value=value+in_matrix[i][a]*in_matrix[j][a]; } value=value/max_j; out_matrix[i][j]=value; } }

So what am I doing wrong here. TIA

Replies are listed 'Best First'.
Re: perlxs and gcc error (use more Perl)
by tye (Sage) on Feb 11, 2003 at 15:21 UTC

    I find that the best XS code (easiest to understand, most robust, nicest interface, etc.) is usually the least XS code. That is, write as much as possible in Perl not in C.

    This means write Perl code to get your data into a format that is easy for C to handle. In this case I'd just make a big flat list of values for both input and output.

    void _do_matrix( char *in, long rows, long cols, char *out ) CODE: long i, j, a; double *in_matrix= (double *)in; double *out_matrix= (double *)out; double value; for( i= 0; i < rows; i++ ) { for( j= i-1; j >= 0; j-- ) { value= 0; for( a= 0; a <= cols; a++ ) { value += in_matri­x[i*cols+a]*in_matrix[j*cols+a]; } value /= (cols-1); out_matrix[i*rows+j]= val­ue; } }
    and then the Perl wrapper:
    sub do_matrix(\@) { my( $avMatrix )= @_; my( $rows )= 0+@$avMatrix; my( $cols )= 0+@{$avMatrix->[0]}; my $in= pack "d*", map @$_[0..$cols-1], @$avMatrix; my $out= pack "d".($rows*$rows); _do_matrix( $in, $rows, $cols, $out ); my @out= unpack "d*", $out; my @ret; while( @out ) { push @ret, [ splice( @out, 0, $rows ) ]; } return \@ret; }
    or something substantially similar after testing finds a few bugs.

                    - tye
      In addition to tye's great advice, I will also suggest that you check out Inline::C, which makes writing XS code almost transparent. You can just embed C code right in your perl code, and not need to worry about a lot of the niggling details of XS.

      I posted a snippet (Pattern for Inline-C-based crunching) to show samples of doing this sort of thing for one-dimensional arrays returning single scalar values. Tye's example is a great way to extend this to get more complex data in and out.



        ...And pick up a copy of "Extending & Embedding Perl". Great Book! It has been a great reference for me.


Re: perlxs and gcc error
by Abigail-II (Bishop) on Feb 11, 2003 at 12:28 UTC
    I don't know whether this is line 19, but in

    you are assuming in_matrix is an array of pointers. However, you have declared in_matrix to be double &in_matrix. Are you sure you don't want double ** in_matrix here?


      Yes, that would be what i want to do. However if i change "double &in_matrix" to "double ** in_matrix", this happens:
      $ make /usr/bin/perl -I/usr/lib/perl5/5.6.1/i386-linux -I/usr/lib/perl5/5.6.1 + /usr/lib/perl5/5.6.1/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.6.1/ +ExtUtils/typemap test_c.xs > test_c.xsc && mv test_c.xsc test_c.c Error: 'double **' not in typemap in test_c.xs, line 8 make: *** [test_c.c] Error 1
        The typemap is a mapping from C types to Perl internal types. There are many predefined types, but as you can imagine, it would be impossible to list them all. It looks like double ** isn't in the typemap (which doesn't quite surprise me). So, you have to either extend the typemap, or use the appropriate Perl internal types.

        I don't know how to extend the typemap. My knowledge of XS is extremely limited.


Re: perlxs and gcc error
by Anonymous Monk on Feb 12, 2003 at 14:08 UTC
    Thanks for all the replys. I'm currently checking into that Inline::C, but in there it seems i have to do the typemap for "double ** matrix". Also i'm going to check how to do the wrapper style. Perhaps combining these would bring best solution.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://234367]
Approved by valdez
Front-paged by broquaint
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (2)
As of 2018-07-19 04:08 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (401 votes). Check out past polls.