-----BEGIN PGP SIGNED MESSAGE----- Hello,
I am trying to design the XS code for the new BigInt package. I had the following idea: * we return a references to a blessed scalar (that seems to be neccessary, e.g. I don't think I can bless the scalar and return it as-is, the RV seems to be necc.) * The referenced scalar should be used to store the stuff I need. The second point is where it gets murky. I need basically to store: * flags and a sign. Both can be put together into an int * A or P (or none, as told by the flags), which can be put into a double * a ptr to the low-level math object (usually a blessed RV) Now, instead of malloc() a struct like: struct BigInt { int flags; int sign; double P; double A; SV* CALC; }; and then putting a ptr to it into the PV slot, I thought I could: put the flags/sign into the IV slot (sign: lower 8 bit, flags the rest) put AP into the NV slot (we only have A or P, never both) put the ptr into the PV slot Problems: * I am not sure this will work. * I have problems calling a Perl routine, and storing it's return value, and later retrieving it. Attached is my very first (well, more like round 246, last attempt) at the code to create an object. Also attached is a small test.pl test-driving this. A more complete module for: perl Makefile.PL make perl -Mblib -Ilib test.pl can be found at http://bloodgate.com/perl/packages/devel/Math-BigInt-XS-2.00.tar.gz I read the "Extending and Embedding Perl" book, but it never told exactly how to call "normal" Perl subroutines from XS - all it talked about was calling them from C (are there differences?) and using them as callbacks (which I don't want to, but it seems similiar, but what are the differences?). The book is actually quite confusing on these issues... The test.pl outputs on my system: SV = RV(0x818d8a4) at 0x8149d3c REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x8149ba4 SV = PVMG(0x8167040) at 0x8149ba4 REFCNT = 1 FLAGS = (OBJECT,POK,pPOK) IV = 1 NV = 2.1 PV = 0x815a358 ""\0 CUR = 0 LEN = 1 STASH = 0x81bbd5c "Math::BigInt" SV = NULL(0x81bc200) at 0x815a358 REFCNT = 0 FLAGS = () The first dump shows the reference and the SV stuffed with my info. The second is the attempt to retrieve the Math::BigInt::Calc object from the PV (a reference to a blessed AV actually), judgin from the matching address (0x815a358) that went ok, but the contents are not what I expected. There is also the problem on DESTROY, I am sure I need a special routine to handle the freeing of the embedded CALC object and my "stuffed" SV. Maybe it would be better to create a RV that points to a blessed RV, which points to the CALC object _and_ contains an IV and NV? In any event, all the easy stuff in Perl like: $CALC->_new( \$wanted ); is hideous complicated in XS, or so it seems. You need like 20-30 lines of very complicated code just to achive this, and even then you haven't taken into account inheritance or changable classnames... *sigh* Thank you for your insight, Tels - -- Signed on Sun Jan 18 13:10:52 2004 with key 0x93B84C15. Visit my photo gallery at http://bloodgate.com/photos/ PGP key on http://bloodgate.com/tels.asc or per email. "I am soo clumsy today." *crash* -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2-rc1-SuSE (GNU/Linux) Comment: When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl. iQEVAwUBQAp7nncLPEOTuEwVAQFz/wf9FDUWwHFie61LI4Ioo6LURYrCJr5KoNrw 2/yaj3TZCdu1AWkyld3MsbrC04ThzbLbCktxVRjmhWk7COl7h24HJjTrbhp5Pcd0 P6tVVVMVeXbJM0o76xIJ394Qa7/LZiLoRzMvs7zMUslxbGGCQ8R0fbVB+vLLptDT wmM5at+i+fo/5mWkJCuL05F98DDDbOfaVp495+6k6kKzNY+UzO7LSZdgMul8RULp MWjlpypQ9lN1deqkL9697uibMa3rsvCNCTXtsZ1F1qgtCmFOFPok18lIKwVqEwIA YNuXtvdQXhWDyKrdRm3DM/lhvYvWSLnu12CbHD6oikr7ZlkI28ZE9A== =OXhy -----END PGP SIGNATURE-----
#!/usr/bin/perl -w use Math::BigInt; use Devel::Size qw/total_size/; use Devel::Peek; my $x = Math::BigInt->new(1); print total_size($x),"\n"; print Dump($x); Dump( $x->_calc_object() );
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" /* Math::BigInt XS code */ /* we store the BigInt info inside a SV: IV & 0xF = sign: 0 => 'NaN', 1 => '+', +2 => 'inf', -1 => '-', -2 => '-inf' IV 0 0xFFF >> 8 = flags: bitmask: bit set means 0 undef (otherwise normal object) 1 use AP to round 2 AP is _A or _P (if bit 1 is set) 0 => AP is _A 1 => AP is _P 3 _F: if set, never round this object PV = ptr to low-level math library object (aka unsigned value) NV = A or P, accuracy or precision (see flags) MODULE = Math::BigInt PACKAGE = Math::BigInt PROTOTYPES: ENABLE ############################################################################## # new() - create a new Math::BigInt object SV* new(class, n) SV* class SV* n PREINIT: dSP; SV* x; SV* rv; SV* calc; int count; PPCODE: ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs ( newSViv( 8 ) ); /* class argument does not matter */ XPUSHs ( n ); PUTBACK; count = call_pv ("Math::BigInt::Calc::_new", G_SCALAR ); SPAGAIN; /* get return arg and make copy of ptr to LIB object */ calc = POPs; SvREFCNT_inc(calc); FREETMPS; LEAVE; rv = sv_newmortal(); newSVrv( rv, "Math::BigInt"); /* now we have rv pointing to a new SV, which we fill with our info */ x = SvRV ( rv ); sv_setuv (x, 0x0001); /* flags => 0, sign => 1 ('+') */ sv_setnv (x, 2.1); /* AP = 0 (2.1 to test it works) */ sv_setpvn (x, (const char*) calc, 0); PUSHs ( rv ); ############################################################################## # return the embedded CALC object for testing SV* _calc_object(x) SV* x PREINIT: SV* rt; SV* rv; PPCODE: /* dereference the RV we get */ rv = SvRV ( x ); rt = SvPV_nolen(rv); PUSHs(rt);