dl.kudish has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am new to perlXS. I am using perl XS(http://perldoc.perl.org/perlguts.html). and writing perl wrapper over my C++ code. I want to return a value of type int64_t from C++ to perl. Please see my code snippet. But it is truncating the value.(of course while compiling itself I am getting this Warning: Conversion of 64 bit type value to "long" causes truncation). In documentation I do not find any information on how to send int64_t (or long) values. Please tell me what i can do here. Thanks in advance D. L. Kumar
SV* get() { int64_t val = ..; if (...){ return &PL_sv_undef; } return newSViv(val); }

Replies are listed 'Best First'.
Re: Returning int64_t value from C++ to Perl
by BrowserUk (Patriarch) on Sep 12, 2008 at 10:46 UTC

    Two possibilities.

    1. Convert the I64 to a double and return it as an NV:
      double i64d ( ) { __int64 x = 123435; return (double)x; }
    2. Return the 8 bytes packed into a string and unpack them in Perl:
      SV* i64p( ) { union { __int64 i; char s[8]; } x; x.i = 123456789; return newSVpv( x.s, 8 ); } ... ## Note: The unpacking will vary with endianness of the platform. my( @i64 ) = unpack 'VV', i64p(); print $i64[ 1 ] * 2**32 + $i64[ 0 ];

    Either way, if you are using a 32-bit Perl, you are going to be restricted to integers < ~2**52, so the latter method would only really be useful if you are going pass the I64 (back) to another piece of i64 capable code.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Returning int64_t value from C++ to Perl
by salva (Canon) on Sep 12, 2008 at 10:54 UTC
    You can:
    • Use a perl compiled with 64bit IVs.
    • Store the number as an NV, on most CPU architectures, NVs (=C doubles) can represent integers of 48 bits (49 including the sign). For instance, if you are representing file offsets, that means 256 Terabytes.
      SV *get() { ... return newSVnv((NV)val); }
      (note that newSVnv() will generate an IV or UV instead of and NV if the data fits inside)
    • Use and external module as Math::Int64 or Math::GMP
    • Return the int64 as a string, converted to decimal or packed.
    Adding a C API to Math::Int64 (I am the author ;-) is in my TODO list. update: DONE!
      Hi, Thanks a lot. Now I am using external module Math::Int64. Thanks D. L. Kumar
Re: Returning int64_t value from C++ to Perl
by Anonymous Monk on Sep 12, 2008 at 10:27 UTC