Ah, this makes doing most of the work in Perl even more important (in my book, anyway). So we need to build a bunch of (packed) C arrays and a (packed) array of C pointers to these arrays. That isn't too hard. Here is some code:
and the XS code would look something like this:sub MyFunc { my $avMatrix= shift(@_); my $packedMatrix= ""; my @recycleBin; my $width= @{ $avMatrix->[0] }; for my $avRow ( @$avMatrix ) { $width= @$avRow if @$avRow < $width; my $packedRow= pack("f$width",@$avRow); push @recycleBin, \$packedRow; $packedMatrix .= pack("p",$packedRow); } return MyFuncC( 0+@$avMatrix, $width, $packedMatrix ); }
int MyFuncC( rows, columns, packedMatrix ) int rows; int columns; char * packedMatrix; CODE: RETVAL= CFunc( rows, columns, (float **)packedMatrix );
Some explanation: A C function that takes a 2-dimensional array (matrix) usually requires that the dimensions of the matrix be passed in. So we need to figure out what to pass in for the width. To prevent the C code from trying to read off the end of the packed arrays that we'll be producing, we just set width to be the minimum width. Another reasonable choice would be to refuse to call the C code if different widths were passed in.
The first pack creates the C (packed) array for a single row of the matrix. We need to prevent the string that contains this packed row from being garbage collected until after the C function is done, so we keep a reference to it alive in @recycleBin until the end of our Perl function.
Then we append a pointer to the start of that packed row to our $packedMatrix, which is just a Perl string that we build up as a packed array of pointers.
- tye (but my friends call me "Tye")In reply to (tye)Re3: Passing References to Arrays into Perl Extensions in C
by tye
in thread Passing References to Arrays into Perl Extensions in C
by Evanovich
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |