in reply to XS: EXTEND/mPUSHi
-
You need to use XSRETURN to specify how many items you placed on the stack. Basically, dSP; creates a local stack pointer and mPUSHi modifies this local pointer, so you need to copy this value back to the real stack pointer.
Instead of figuring out what argument to use for XSRETURN, you can use PUTBACK. Unlike XSRETURN, it doesn't perform a return, so you need to follow it up with return if you use it in the middle of a function.
XS would normally do this for you, but Inline::C forces you to do it (by using return; /* assume stack size is correct */).
This was the purpose of Inline_Stack_Done.
-
The scalars passed to the sub are still on the stack, so you need to remove them unless you want to return them.
In Perl ops, this would be done by popping them as they are read, but one doesn't tend to read them when using Inline. SP = MARK; will pop all of them.
This was the purpose of Inline_Stack_Reset.
-
If rnd(100) should return 100 numbers, you need to use a post-decrement for your loop counter.
orvoid rnd( int n ) { static __int64 y = 2463534242; dXSARGS; int i; POPs; EXTEND( SP, n ); for (i = n; i--; ) { y ^= y << 13; y ^= y >> 17; y ^= y << 5; mPUSHi( (IV)y ); } XSRETURN(n); }
void rnd( int n ) { static __int64 y = 2463534242; dSP; dMARK; SP = MARK; // Remove args from stack. EXTEND( SP, n ); while (n--) { y ^= y << 13; y ^= y >> 17; y ^= y << 5; mPUSHi( (IV)y ); } PUTBACK; // Publish changes to stack. }