Your skill will accomplish what the force of many cannot |
|
PerlMonks |
First contact with XS passing arrays, or: Request for a tutorialby jeroenes (Priest) |
on Feb 21, 2001 at 14:07 UTC ( [id://59891]=perlmeditation: print w/replies, xml ) | Need Help?? |
Last week, I have been writing my first perl extension. I wanted to conclude my experiences with a description of the hickups, because I was a little surprised by how little nodes here actually provide some help with XS. This really is a request for a tutorial on how to pass arguments to/from XS.
Start offActually, the start was pretty straightforward. I printed perlxs, perlxstut, and perlguts, and took off. I followed perlxstut, and with h2xs I promptly obtained a framework to start with.
First lines of codeI copy/pasted the single C-function I wanted to implement (a smoother) into the CODE block, made up some name, and than I landed at the first quirk: the code needed some C-macro, and I had no clue from the docs where to put it. I glanced through the files found by 'locate .xs', and quickly saw you just can put them before the function declaration. Did so, and it worked.
Float *?Than I came at the point I wanted to pass my arguments. I had some arrays, some ints and some floats, and the C-code used floats. I first started with the ints, no problem, and than the floats. OK, than the array with float *, as in the C-function declaration. Here came the first errors from gcc: the XS interface did not recognize float *. I read up in the tut: It mentioned to use a typemap. An example was to be found in the perl source. Indeed, somewhere buried in the ext/ tree I found some typemaps, and I hit one with a float * line. Well, that didn't work at all. Again, I browsed through all the .xs on my box, but didn't find any that actually interfaced with a float *.
ArraysThan I stumbled across the perlguts (I had printed it for some reason!), and it mentioned ways to implement perl-arrays in C. Well, I tried AV * and variations on the theme without getting any sensible array-item across. A perlmonks search did wonders: I found a reply by tye, and he basically said to pack your array, and interface it by char *, and typecast it with (double *). This worked like a charm, I had my variables in C. The original code used an array type rather than a pointer, so I had to convert it into a c-array in a loop. Lots of conversions, but it worked. In the module, I implemented the pack/unpack conversions, so all became transparant for the end-user (me ;).
Output arraysOf course I thought, for the output I take a pointer to my array, than cast that back to a char *, and there I am. No way! Whatever variation on this, I got the value of the pointer back at most. So I had to come up with something else, and I finally got meself some succes by declaring a perl-scalar. It goes like:SV is the internal name for a scalar (AV for array; HV for hash, see perlguts). NewSVpv assigns some string to that scalar. When passing a string without \000 termination (aka 'pascal string'), you need to tell how much bytes you wanna have, here the number of items times the sizeof(double). Put out like this, it works like a charm. Crunches some 100 times faster than the routine I used in matlab, and it can be called from within perl.
Tutorial?All together, I think I would have liked some elaboration in a tutorial on howto pass arguments between C and perl. For example, ints go without a problem, but the arrays are a horror, and I didn't even touch arrays of strings or even hashes. I would be delighted if someone has written/ would like to write a tutorial on the subject, to help stumbling starters like myself.
Jeroen
Back to
Meditations
|
|