Menu

#1079 Problems with long/jlong and int64_t on 64-bit platforms

None
closed-fixed
java (79)
5
2023-12-20
2010-03-09
No

Hi,

I am using SWIG 1.3.39 and GCC 4.4.1 (Ubuntu 4.4.1-4ubuntu9) on Ubuntu 9.10 (Linux efriedma-ux 2.6.31-19-generic #56-Ubuntu SMP Thu Jan 28 02:39:34 UTC 2010 x86_64 GNU/Linux).

Normally on 64-bit Linux, int64_t is defined to be a `long int`. However, in SWIG (at least for Java), it is defined incorrectly, as seen in the following simple interface file:

// foo.i
%module foo
%{
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
BOOST_STATIC_ASSERT(( boost::is_same<int64_t, jlong>::value ));
%}

This may be compiled as follows:

$ swig -c++ -java foo.i
$ g++ foo_wrap.cxx
foo_wrap.cxx:216: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'

The error means the Boost static assertion has failed, which indicates that `int64_t` and `jlong` are not the same type. (The result is the same even if I include the SWIG import <stdint.i>.)

However, the following C++ program, which has the same check compiles without a problem:

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
int main()
{
BOOST_STATIC_ASSERT(( boost::is_same<int64_t, jlong>::value ));
return 0;
}

Trying to track this down, it seems as though the problem is due to the following lines in the SWIG-generated source file (foo_wrap.cxx):

/* Fix for jlong on 64-bit x86 Solaris */
#if defined(__x86_64)
# ifdef _LP64
# undef _LP64
# endif
#endif

Doing this causes the JNI headers to make the `jlong` type as a typedef for `long long int`. I don't understand why this is being done, as it's different from `int64_t`.

Thanks,

Eric

P.S. Looking at the Subversion history for this change, I came across the following:

http://swig.svn.sourceforge.net/viewvc/swig?view=rev&revision=6891

The commit message (from marcelomatus) is "fix warning(error?) with jlong + x86_64". Does that give any clue as to why this introduced? Are there other problems with SWIG on 64-bit platforms? (The uncertainty in the commit message is a bit unnerving.)

Discussion

  • Eric Friedman

    Eric Friedman - 2010-03-09

    Generated foo_wrap.cxx

     
  • Eric Friedman

    Eric Friedman - 2010-03-09

    Also forgot to mention: I also checked with the latest version of SWIG (1.3.40), and it seems that this issue is still present there as well.

     
  • Eric Friedman

    Eric Friedman - 2010-03-10
    • summary: int64_t defined incorrectly --> Problems with long/jlong and int64_t on 64-bit platforms
     
  • Eric Friedman

    Eric Friedman - 2010-03-10

    Looking further into this issue, I've come to the conclusion it's not just `int64_t` that's being defined incorrectly on 64-bit platforms but also `long` is being incorrectly typemapped. Specifically, it seems that at least the Java support in SWIG assumes a 32-bit target.

    In particular, a C `long` is always mapped to a Java `int` (`jint`). However, on 64-bit platforms, a `long` is 64-bits and should be treated as a Java `long` (`jlong`). The same issue applies also for `unsigned long`.

    I think what should be happening is that typemaps for `long` should not be defined at all. Instead, depending on the platform, either the typemaps for `int` (on a 32-bit platform) or for `long long` (on a 64-bit platform) should be copied (using %apply) to handle `long`. I've modified my java/java.swg accordingly (and removed the _LP64 business in java/javahead.swg) and it seems to solve the problem. I'll see if I can post a patch in the next few days.

     
  • Eric Friedman

    Eric Friedman - 2010-03-10

    Also, there is a further problem for 64-bit platforms (though seemingly unrelated):

    swigarch.i seems to be broken unless SWIGWORDSIZE64 is manually defined (e.g., using -DSWIGWORDSIZE64). I see this has been reported elsewhere (http://old.nabble.com/-BUG--stdint.i-gets-int64_t-wrong-on-64bit-archs-td20695275.html) as well.

    Unlike the issue with the core typemaps, this issue can at least be worked around in a straightforward way with the -D option. But to fix it correctly though seems to require changing the actual SWIG code generator (i.e., to automatically define a preprocessor symbol like __x86_64 or __WORDSIZE while processing interface files).

     
  • Eric Friedman

    Eric Friedman - 2010-04-23

    Fixes the issue with Java

     
  • Olly Betts

    Olly Betts - 2022-02-01

    The dubious undefining of _LP64 was removed in 971e1154af7a608a0f2f96ee98189da4aa001412 which will be in the upcoming SWIG 4.2.0 release.

    The other points don't seem to have been addressed yet.

    Note that SWIG aims to generate code that's independent of the architecture of the machine that it's run on, so we shouldn't be defining things like __x86_64 or __WORDSIZE during processing of the interface file but rather generating code that has suitable conditionals on symbols the compiler would then define or not.

     
  • Olly Betts

    Olly Betts - 2023-12-20
    • status: open --> closed-fixed
    • Group: -->
     
  • Olly Betts

    Olly Betts - 2023-12-20

    This recent commit (which will be in SWIG 4.2.0) looks like it addresses the remaining points here:

    commit 7bba06b03ef4529c542c3cf8364c382027aae000
    Author: William S Fulton <wsf@fultondesigns.co.uk>
    Date:   Wed Sep 27 07:46:53 2023 +0100
    
        Java - SWIGWORDSIZE64 for long type
    
        Defining SWIGWORDSIZE64 now applies the (unsigned) long long
        typemaps to (unsigned) long for a better match on systems
        where long is 64-bits.
    
        Although size_t typemaps are now applied from the int typemaps instead
        of the long typemaps, identical code is generated and the mapping is
        still to the Java signed long type.
    
        Closes #646
        Closes #649
    
        Running the test-suite as follows on a 64-bit long system:
    
          env SWIG_FEATURES=-DSWIGWORDSIZE64 make check-java-test-suite
    
        passes, except for a few tests which fail where they expect the
        default Java type to be int or long instead of long or BigInteger
        respectively.
    
        Also arrays_java.i results in:
          invalid conversion from long int* to long long int* [-fpermissive]
          invalid conversion from long int** to long long int** [-fpermissive]
    
     

Log in to post a comment.