Notes to self:
My first naive attempt went something like this:
my @integers = (4, 2, 1, 5, 6, 3);
print +choose(\&lessthan, scalar @integers, @integers);
print +choose(\&grtrthan, scalar @integers, @integers);
__DATA__
__C__
#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
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);
}