slowly going through perlapi

stvn_skuo on 2005-02-05T22:00:43

Notes to self:



  • With Inline::C, arguments to variadic C functions should be processed with Inline_Stack_Item(s), instead of the functions declared in <stdarg.h>.

  • Calling Perl subroutines from C? Better start reading perlguts, perlapi, and perlcall.



I don't do any XS programming, but I do use C often enough to think learning Inline to be worthwhile and, well, fun. After my first experience with Inline, I really have to give kudos to those in /p\d+p/ who so deftly handle three disciplines (e.g, Perl, C, and XS).



My first naive attempt went something like this:



use Inline 'C';

my @integers = (4, 2, 1, 5, 6, 3);

print +choose(\&lessthan, scalar @integers, @integers); print +choose(\&grtrthan, scalar @integers, @integers);

__DATA__ __C__

#include #include #include

int lessthan (int a, int b) { return (a < b) ? a : b; } int grtrthan (int a, int b) { return (a > b) ? a : b; } int choose( int(*fn)(), size_t count, int first, ...) { va_list arg_ptr; int next; int keep; va_start(arg_ptr,count); keep = va_arg(arg_ptr, int); for(--count; count > 0; --count) { next = va_arg(arg_ptr, int); keep = fn(keep, next); } return keep; }



In retrospect, other than as a learning exercise, this wasn't an ideal test of Inline::C. There's no speed advantage over a pure perl implementation. I ended up with something that seems to be half C and half XS:





use Inline 'C'; my @integers = (4, 2, 1, 5, 6, 3);

local $\ = "\n"; print +choose(\&lessthan, @integers); print +choose(\&grtrthan, @integers);

__DATA__ __C__

#include #include

int lessthan (int a, int b) { return (a < b) ? a : b; } int grtrthan (int a, int b) { return (a > b) ? a : b; } int choose(CV *fn, int first, ...) { SV *next_sv; SV *keep_sv; unsigned int count;

Inline_Stack_Vars;

keep_sv = newSVsv(Inline_Stack_Item(1)); for(count = 2; count < Inline_Stack_Items ; ++count) { I32 retval; dSP; ENTER; SAVETMPS; next_sv = newSVsv(Inline_Stack_Item(count)); PUSHMARK(SP); XPUSHs(sv_2mortal(newSVsv(keep_sv))); XPUSHs(sv_2mortal(next_sv)); PUTBACK; retval = call_sv((SV *)fn, G_SCALAR); SPAGAIN; if (retval != 1) { croak("Big trouble\n"); } sv_setsv(keep_sv, POPs); FREETMPS; LEAVE; } Inline_Stack_Reset; Inline_Stack_Done; return (int)SvIV(keep_sv); }


More reading

stvn_skuo on 2005-02-06T19:18:36

I'll have to take a minute and study this ... http://perlmonks.org/?node_id=428371