in reply to Re^2: accessing mpz_t * of Math::BigInt::GMP from XS
in thread accessing mpz_t * of Math::BigInt::GMP from XS

Yes, I eventually got around to passing $obj->{value}, but there's probably still something I'm missing. The following works for me - but it avoids a lot of the pre-processor stuff that Math::BigInt::GMP's GMP.xs contains, and I therefore wonder about its portability
use Math::BigInt lib => 'GMP'; use Inline C => Config => LIBS => '-lgmp', USING => 'ParseRegExp', BUILD_NOISY => 1; use Inline C => <<'EOC'; #include <gmp.h> mpz_t * mpz_from_sv_nofail (SV *sv) { MAGIC *mg; if (!sv_derived_from(sv, "Math::BigInt::GMP")) croak("not of type Math::BigInt::GMP"); mg = SvMAGIC(SvRV(sv)); return (mpz_t *)mg->mg_ptr; } mpz_t * mpz_from_sv (SV *sv) { mpz_t *mpz; if (!(mpz = mpz_from_sv_nofail(sv))) croak("failed to fetch mpz pointer"); return mpz; } void my_mul(SV * bi_rop, SV * bi_op, SV * si) { mpz_t *t1, *t2; t1 = mpz_from_sv(bi_rop); t2 = mpz_from_sv(bi_op); mpz_mul_si(*t1, *t2, SvIV(si) * 10); } EOC my $rop = Math::BigInt->new(0); my $op = Math::BigInt->new(123456); my $x = -110; my_mul($rop->{value}, $op->{value}, $x); print $rop, "\n"; __END__ Outputs: -13580160
I also wonder:
1) How is the change of sign being effected by my_mul() - given that it should be working only with 'value';
(Update: Setting $op to -123456 and multiplying by -110 still results in an output of -13580160. So 'sign' is *not* being dealt with correctly ... which is what I expected. )
2) Why do I have to multiply the 3rd arg of my_mul() by 10 in order to have it produce the correct value in the Math::BigInt::GMP object.

I'm sure there's a very good (and likely very simple) explanation for both.

Cheers,
Rob

Replies are listed 'Best First'.
Re^4: accessing mpz_t * of Math::BigInt::GMP from XS
by syphilis (Archbishop) on Mar 19, 2011 at 04:34 UTC
    Eventually got it down to the following (which works correctly for me, afaik):
    use Math::BigInt lib => 'GMP'; use Inline C => Config => LIBS => '-lgmp', USING => 'ParseRegExp', BUILD_NOISY => 1; use Inline C => <<'EOC'; #include <gmp.h> mpz_t * mpz_from_sv_nofail (SV *sv) { MAGIC *mg; if (!sv_derived_from(sv, "Math::BigInt::GMP")) croak("not of type Math::BigInt::GMP"); mg = SvMAGIC(SvRV(sv)); return (mpz_t *)mg->mg_ptr; } void _my_mul(SV * bi_rop, SV * bi_op, SV * si, SV * rop_sign, SV * op_ +sign) { mpz_t *t1, *t2; sv_setpv(rop_sign, SvPV_nolen(op_sign)); t1 = mpz_from_sv_nofail(bi_rop); t2 = mpz_from_sv_nofail(bi_op); mpz_abs(*t2, *t2); mpz_mul_si(*t1, *t2, abs(SvIV(si))); if(SvIV(si) < 0) { if(strEQ(SvPV_nolen(op_sign), "-")) sv_setpv(rop_sign, "+"); else sv_setpv(rop_sign, "-"); } } EOC my $rop = Math::BigInt->new(0); my $op = Math::BigInt->new(-123456); my $x = 1103; my_mul($rop, $op, $x); print $rop, "\n"; my_mul($op, $op, 5); print $op, "\n"; sub my_mul { _my_mul($_[0]->{value}, $_[1]->{value}, $_[2], $_[0]->{sign}, $_[1]- +>{sign}); }
    Cheers,
    Rob