Ruby/DL: bignum->long

Discussion in 'Ruby' started by Jamis Buck, Oct 23, 2004.

  1. Jamis Buck

    Jamis Buck Guest

    Using Ruby/DL, it seems as though a 32-bit integer with the MSB set
    cannot be converted to a long integer:

    require 'dl'

    DL::dlopen("libc.so.5") do |libc|
    isdigit = libc['isdigit', 'CH']
    p 0x40000000.class
    print(isdigit.call(0x40000000), "\n")
    p 0x80000000.class
    print(isdigit.call(0x80000000), "\n")
    end

    The above will print the first one successfully, even though 0x40000000
    is a Bignum. The second one results in an error:

    in `call': bignum too big to convert into `long' (RangeError)

    Is this a bug, or a feature? Is there a workaround? Any advice would be
    appreciated.

    Thanks,

    Jamis
     
    Jamis Buck, Oct 23, 2004
    #1
    1. Advertisements

  2. I think the call is failing because of some code in bignum.c:

    lines 765-776:

    long
    rb_big2long(x)
    VALUE x;
    {
    unsigned long num = big2ulong(x, "long");

    if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) {
    rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
    }
    if (!RBIGNUM(x)->sign) return -(long)num;
    return num;
    }

    It checks to see if the number goes negative when trying to convert it
    to a long, and if so, raises an exception. In this case you are using
    a hex value to set an integer that you intend to be negative, but Ruby
    treats this as a positive integer. Perhaps you could get around it by
    putting the number in as a negative:

    #!/usr/bin/env ruby

    require 'dl'

    DL::dlopen("libc.dylib") do |libc|
    isdigit = libc['isdigit', 'CH']
    p 0x40000000.class
    print(isdigit.call(0x40000000), "\n")
    p -2147483648.class
    print(isdigit.call(-2147483648), "\n")
    end

    Here is the output:

    Bignum
    01073741824
    Bignum
    0-2147483648
     
    Carl Youngblood, Oct 23, 2004
    #2
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.