Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

First contact with XS passing arrays, or: Request for a tutorial

by 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 off

Actually, 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 code

I 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 *.

Arrays

Than 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 arrays

Of 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 * array_out; //the code array_out = newSVpv( (char *) z, m * 8 ); RETVAL = array_out; OUTPUT RETVAL
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
"We are not alone"(FZ)

Replies are listed 'Best First'.
Inline::C
by Tyke (Pilgrim) on Feb 21, 2001 at 17:32 UTC
    Since you asked for more info in the CB.:

    "Inline::C is a module that allows you to write Perl subroutines in C". There a whole cookbook available with plenty of examples, everything from a 'hello world' to calling up Windows Messages boxes. The C module is generated, compiled and cached, the first time it is invoked. If you modify the C code, it rebuilds the cached module automagically.

    You can pick it up from CPAN (including cookbook). The whole thing even works on Windoze, (though if you're using ActiveState's perl, you'll need to have Visual Studio).

    Enjoy...

      Aha, thank you Tyke! The cookbook discusses all the problems I was referring to. Well, if only I would have found that earlier....

      Jeroen
      "We are not alone"(FZ)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://59891]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2024-03-29 06:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found