If you end up with something that works, that's a good thing. My thinking is that the direction I'm suggesting above is extremely clearly good practice, and there's a reason that good practice is considered desirable: it avoids errors and/or unnecessary maintenance work.
If the C functions you wrote and then let Inline::C do its stuff with take/return SVs, I'd suggest that's a category error, and they should instead take/return mpz_t values (or pointers thereto). With the right typemap entries, you could just write XS functions that take/return mpz_t values, and omit the Inline::C stuff, which isn't as necessary as you might think, once you have all the typemap, CODE: and OUTPUT: stuff working, which you evidently do.
Having had a very quick look at https://github.com/sisyphus/math-gmpz/blob/master/typemap, is there a reason all those identical "types" aren't just the one? If you gave an OUTPUT clause as well, that would significantly facilitate the idea above. PDL's typemap can be used as a quite good template. | [reply] |
Thanks for the input.
There's some thoughts there that probably gel with a lot of people. They also gel with me to some extent.
The attraction for me of taking/returning SVs in the C function is that I don't always know precisely what is being taken/returned.
For example, with the overload routines, I know that the first arg will always be a Math::GMPz object (and I'll probably now get around to changing that first arg from SV* to mpz_t* in those routines), but the 2nd arg can be any one of an IV, NV, PV, or a number of different objects (Math::GMPz, Math::GMPq, Math::MPFR, etc.).
It's convenient to just call it an SV and then let the overload routine work out exactly what it is, and how to deal with it.
Similarly, not all of those overload routines always return a Math::GMPz object - sometimes some of them may return a Math::GMPq or Math::MPFR object.
Again, it's nice to just specify the return as an SV* and let the typemapping sort out exactly what it is.
Now, admittedly, I could do away with the C functions altogether, and have everything done inside the XS subs, but that's just putting the spaghetti into the meatballs.
There's nothing wrong with that, but I'm quite happy to have the spagehetti and the meatballs kept adjacent to each other. Changing that aspect of the current procedure strikes me as being more trouble than it's worth.
But having said that, I do see an opportunity to remove a lot of simple C functions - which I intend to do.
Having had a very quick look at https://github.com/sisyphus/math-gmpz/blob/master/typemap, is there a reason all those identical "types" aren't just the one?
I don't think their identical. I believe that all occurrences of "$type" and "$var" represent separate, unique values.
It's probably only mpz_t, mpq_t and gmp_randstate_t that need to be specified.
I guess the other ones are there just in case they're ever needed.
Thanks again, etj.
Cheers, Rob
| [reply] [d/l] [select] |
(Re https://github.com/sisyphus/math-gmpz/blob/master/typemap)
I don't think their(sic) identical. I believe that all occurrences of "$type" and "$var" represent separate, unique values.
Well they do once ExtUtils::ParseXS expands them. There's a reason they're in there as $variables. If you make that typemap read as just this:
mpq_t * GMP_PTR
mpz_t * GMP_PTR
mpf_t * GMP_PTR
mpfr_t * GMP_PTR
gmp_randstate_t * GMP_PTR
INPUT
GMP_PTR
$var = INT2PTR($type, SvIVX(SvRV($arg)))
It still works correctly. (Yes, I just tried it) As a matter of fact, the Perl-supplied typemap includes an entry already that does the above, but better because it also checks the SV is a ref first:
mpq_t * T_PTRREF
mpz_t * T_PTRREF
mpf_t * T_PTRREF
mpfr_t * T_PTRREF
gmp_randstate_t * T_PTRREF
| [reply] [d/l] [select] |