Question

Is there any way to force an integer type using LuaJava? I am attempting, in LuaJ 3.0 beta 1 (luaj-jse-3.0-beta1.jar), to create an instance of a java.awt.Color. You wouldn't think this would be such an issue, given the Java API availability of constructors (JavaAPI). The reason I am interested in forcing an integer into the constructor is that the Color constructors available take three and four arguments of either int or float. Since Lua's number type is double, LuaJ (or LuaJava) calls the float versions of the constructors.

At first, I thought this wasn't going to be a problem, but after trying to use it, I noticed that I was receiving an errant Color. The values were not being passed properly into the constructor, and Color object was essentially broken, with no discernible error (it didn't crash anything, it just didn't display).

Here's a quick example:

local j_color = luajava.newInstance( "java.awt.Color", r, g, b );
print( j_color );

If I pass r = 1.0, g = 0.2, b = 0.2 to this constructor, and then print j_color, I will see

java.awt.Color[r=0,g=0,b=1]

in the output. In fact, I can use anything I want in r and g as long as b = 0, with no problem, but otherwise, it causes pain and suffering.

I am a little curious to know if anyone else has encountered this problem. If it doesn't resolve, I will contact the PI on the LuaJ project about it, and report back.

As a side note: it would be a simple matter to construct a solution by which I use a custom-made Java function to be responsible for creating the Color. I am more concerned that this problem exists, and whether there is some way to either specify which constructor you want to use, or to explicitly tell LuaJava to use integers, rather than doubles.

Update

I have also attempted to use the four-float constructor, and the same issue appears. If I pass in one of the following values: alpha=0, 0.5, 1 the constructor functions properly. Anything else will yield the result above.

Was it helpful?

Solution

The functions math.floor() and math.ceil() round down and up and always produce an integer.

For java.awt.Color, you may be better off using the single-integer constructor, since there is not a float equivalent. That way the same constructor will be chosen every time.

Here's a working example:

-- return Java Color with r, g, b as floats in range [0,1]
function color(r, g, b) 
    local ir = math.floor(r * 255)
    local ig = math.floor(g * 255)
    local ib = math.floor(b * 255)
    local packed_rgb = ir*(256*256) + ig*256 + ib
    return luajava.newInstance("java.awt.Color", packed_rgb)
end

The failure case you provided will then have the expected result:

-- test the example
print( color(1, .2, .2) )

> java.awt.Color[r=255,g=51,b=51]

The issue is with runtime selection of overloaded functions based on numeric types. For the java Color class, there are so many overloads that it triggers a bug in the selection logic within luaj for numbers whose float and double values differ slightly (i.e. .2).

Long-term it may be better if luaj exposes a mechanism to get at specific methods based on their full call signatures, but as of luaj-3.0-beta3, this looks to be the most reliable way to invoke the overload you want.

OTHER TIPS

You can force luaj to use the 3 float constructor as follows:

function color(r,g,b)
    r = luajava.newInstance("java.lang.Float",r)
    g = luajava.newInstance("java.lang.Float",g)
    b = luajava.newInstance("java.lang.Float",b)
    return luajava.newInstance("java.awt.Color",r,g,b)
end

You can, of course, do something similar to force luaj to use one of the other overloaded constructor forms.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top