Tels <[EMAIL PROTECTED]> writes:
>-----BEGIN PGP SIGNED MESSAGE-----
>
>Moin,
>
>On Saturday 10 January 2004 19:22, Nick Ing-Simmons wrote:
>> Tels <[EMAIL PROTECTED]> writes:
>> >-----BEGIN PGP SIGNED MESSAGE-----
>> valgrid is complaining about XS_Math__BigInt__GMP_DESTROY
>> can we see that please?
>
>##############################################################################
># DESTROY() - free memory of a GMP number
>
>void
>DESTROY(n)
>        mpz_t*  n
>
>  PPCODE:
>    mpz_clear(*n);
>    free(n);

If it is in a SvPV then you don't call free().


>
>Sorry, should have included it. Here is the typemap, too:
>
>mpz_t *         MPZ
>
>INPUT
>MPZ
>        if (sv_derived_from($arg, \"Math::BigInt::GMP\")) {
>            IV tmp = SvIV((SV*)SvRV($arg));
>            $var = ($type) tmp;
>        }
>        else
>            croak(\"$var is not of type Math::BigInt::GMP\")
>
>OUTPUT
>MPZ
>        sv_setref_pv($arg, \"Math::BigInt::GMP\", (void*)$var);

The typemap is wrong. The OUTPUT side puts thing in SvPV the input side 
gets it from SvIV. 
Which is right depends on how mpz_t's are allocated.
If they are malloc()ed then SvIV style is correct and you can use DESTROY 
as above with free(). But _something_ needs to make sure only one SV 
owns the mpz_t * and so free() only happens once.

Alternatively if mpz_t is stored as opaque binary data in string part of 
SV (SvPV) then OUTPUT still isn't right as binary data will respond badly 
to being strcpy() to the PV, and INPUT is wrong as it is looking in 
wrong SV slot. Also in this case you don't need to free() as SvPV 
will be Safefree()'d by perl. This scheme works quite well with 
perl's SvREFCNT keeping track of when data can go. 

>> >      mpz_abs (*x, *x);
>> >      PUSHs(sv_setref_pv(sv_newmortal(), "Math::BigInt::GMP", (void*)x));
>>
>> That is probably wrong. A pv is a char * and perl is going to do strlen()
>> on it and strcpy() it into memory allocated by perl's New().
>> My guess is x is already malloc()'ed or C++ new'ed by mpz stuff.
>> In such cases it is usual to use sv_setref_iv(...,PTR2IV(x)),
>> and then have DESTROY function call the inner library's free() routine.
>> If *x is a struct then it may also be apprpriate to put the struct
>> as binary data in a PV - but there isn't a handy create-blessed-ref
>> function to do that, you need to do it long-hand
>> something like:
>>
>>   SV *sv = sv_bless(new_RV(newSVpv(x,sizeof(*x))),gv_stashpv("...", TRUE));
>>
>> (Trying to do that in one expression may be too rich for some compilers
>> when all macros are expanded.)
>
>The typemap should do something like that, so I should be able just to copy 
>it's code, right?

You could copy its code if its code was correct.
But to match input it should be 
     sv_setref_iv(...,PTR2IV(x))

>
>       sv_setref_pv($arg, \"Math::BigInt::GMP\", (void*)$var);
>
>Looks the same to me. (But the typemaps INPUT looks funny to my naive eyes..)
>
>> The other issue you _may_ be having is that *x came in from an SV
>> (possibly tempoary). Unless *x is refcounted in mpz library you need
>> get library to give you a new one to return from the XSUB to another perl
>> SV, or change perl view of API to mimic the library's modify-in-place
>> semantics. Otherwise both SVs will call DESTROY and try and free(x).
>
>Thank you for your explanations. This is still a little bit over my head, I'll 
>see if I can make heads or tail out of this tomorrow morning.
>

Reply via email to