8000 [luajit] mlua does not recognize `LL`/`ULL` numbers as integers · Issue #580 · mlua-rs/mlua · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[luajit] mlua does not recognize LL/ULL numbers as integers #580

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed 8000
flip1995 opened this issue May 13, 2025 · 3 comments
Closed

[luajit] mlua does not recognize LL/ULL numbers as integers #580

flip1995 opened this issue May 13, 2025 · 3 comments

Comments

@flip1995
Copy link
flip1995 commented May 13, 2025

In LuaJIT

Plain numbers are always floating-point numbers in LuaJIT because it's compatible with Lua 5.1.

LuaJIT/LuaJIT#1286

To force integers in luajit, you have to add the suffix LL or ULL. But when doing this and implementing something like

impl UserData for MyStruct {
    fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
        fields.add_field_method_set("foo", |_, this, value: u64| {
            this.foo = value;
            Ok(())
        })
    }
}

the following error is emitted:

Lua(
    CallbackError {
        traceback: "stack traceback:\n\t[C]: in function 'field_setter'\n\t[string \"__mlua_newindex\"]:8: in function '__newindex'\n\t/path/to/file.lua:5: in main chunk",
        cause: BadArgument {
            to: Some("MyStruct.foo"),
            pos: 2,
            name: None,
            cause: FromLuaConversionError { 
                from: "other",
                to: "u64",
                message: Some("expected number or string coercible to number")
            }
        }
    }
)

when trying to set MyStruct.foo = 0ULL in a script run through mLua.

@flip1995 flip1995 changed the title mlua does not recognize LL/ULL numbers as integers [luajit] mlua does not recognize LL/ULL numbers as integers May 13, 2025
@khvzak
Copy link
Member
khvzak commented May 13, 2025

This is because objects like xLL or xULL are not numbers actually, they are cdata.

$ luajit -e "print(type(123ULL))"
cdata

LuaJIT through their C API (e.g. lua_tonumber) does not support converting these objects to numbers.

Even LuaJIT standard stdlib methods cannot work with this type, see:

$ luajit -e "math.abs(123LL)"
luajit: (command line):1: bad argument #1 to 'abs' (number expected, got cdata)
stack traceback:
	[C]: in function 'abs'
	(command line):1: in main chunk
	[C]: at 0x010065ee3c

$ luajit -e "table.insert({}, 1LL, 123)"
luajit: (command line):1: bad argument #2 to 'insert' (number expected, got cdata)
stack traceback:
	[C]: in function 'insert'
	(command line):1: in main chunk
	[C]: at 0x0104b1ae3c

So this is rather luajit issue. There is little that can be done here.

@flip1995
Copy link
Author

I see, thanks for the information!

Is there a way how the type of value can be adjusted here:

fields.add_field_method_set("foo", |_, this, value: u64| {
    this.foo = value;
    Ok(())
})

so that it accepts the cdata type? Ideally that it accepts either cdata or u64 and internally converts it? One way would be to define our own type and implement FromLua for it, I guess.

@flip1995
Copy link
Author
flip1995 commented May 14, 2025

One way would be to define our own type and implement FromLua for it, I guess.

So this is what I implemented now:

#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
struct CInt<T>(T);

macro_rules! impl_cint {
    ($(($ty:ty, $suffix:literal)),*) => {
        $(
        impl FromLua for CInt<$ty> {
            fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Self> {
                if let  mlua::Value::Other(_)= value {
                    let str = value.to_string()?;
                    if let Some(int_str) = str.strip_suffix($suffix) {
                        if let Ok(int) = int_str.parse::<$ty>() {
                            return Ok(CInt(int));
                        }
                    }
                }
                Ok(CInt(<$ty>::from_lua(value, lua)?))
            }
        }
        )*
    };
}

impl_cint!((u64, "ULL"), (i64, "LL"));

And the UserData field impl becomes:

fields.add_field_method_set("foo", |_, this, value: CInt<u64>| {
    this.foo = value.0;
    Ok(())
})

Closing this issue, as there isn't really anything that can be done in mlua. But now this is documented in the mlua issues :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0