Re: Wrapping long doubles in python

Olly Betts via Swig-user <[email protected]> Mon, 26 May 2025 12:10:43 +1200
Newsgroups gmane.comp.programming.swig
Message-ID <[email protected]>
On Thu, Jan 30, 2025 at 02:32:15PM -0800, Ayman Habib wrote:
> I'm upgrading the swig version we use from 4.1.1 to 4.2 and running into a
> problem because of the macro below (it appears in a header file from a
> third party library that I can't change), but I get the same behavior
> inserting the line in my .i file:
> 
> #define MY_PI 3.1415926535897L
> 
> The resulting python code doesn't compile:
> 
>   SWIG_Python_SetConstant(d,
> "MY_PI",SWIG_NewPointerObj(SWIG_as_voidptr(&3.1415926535897),SWIGTYPE_p_long_double,
> 0 ));

Prior to 4.2.0, SWIG quietly incorrectly treated all floating point
literals as being type `double` (so suffixes like `L` above or `f` to
specify a `float` literal were just ignored).

For `long double` in particular that's potentially bad - presumably the
long double type was chosen for a reason, but SWIG's wrapping was
quietly discarding the extra precision this provides.  Using the wrong
types here was also getting in the way of improving support for C++
`auto` and `decltype`.

However SWIG doesn't currently provide long double typemaps (except for
a Python doctype one):

https://github.com/swig/swig/issues/2964

So the upshot is the error you report, but that seems better than quietly
wrapping a constant with a different value to the one specified in the
header being wrapped.

If you're happy with the previous situation of truncating the precision
to that of double then you can just tell SWIG to wrap the constant as a
double by adding this near the top of your interface file:

%constant double MY_PI;
%warnfilter(SWIGWARN_PARSE_REDEFINED) MY_PI;

This should also work with older SWIG versions.

Cheers,
    Olly