Ruby/DL: bignum->long

J

Jamis Buck

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
 
C

Carl Youngblood

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
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top