mlua icon indicating copy to clipboard operation
mlua copied to clipboard

How do I return reference to a userdata?

Open Seefaaa opened this issue 1 year ago • 0 comments

How do I return a reference to a userdata? I've read the examples but I couldn't understand how to do this. I need to return a mutable userdata reference to lua so that I can modify the userdata from lua side.

Here's an example of what I'm trying to do:

use mlua::prelude::*;

#[derive(Clone, Default)]
struct MyUserData(Vec<u32>, Vec<MySecondUserData>);

#[derive(Clone)]
struct MySecondUserData {
    a: u32,
    b: String,
}

impl LuaUserData for MyUserData {
    fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
        methods.add_meta_function(LuaMetaMethod::Call, |_, ()| Ok(Self::default()));

        methods.add_method("len", |_, this, ()| Ok(this.0.len() as i64));
        methods.add_method_mut("push", |_, this, val: u32| {
            this.0.push(val);
            Ok(())
        });
        methods.add_method("get", |_, this, idx: usize| Ok(this.0.get(idx).cloned()));

        methods.add_method_mut("push_second", |_, this, (a, b): (u32, String)| {
            this.1.push(MySecondUserData { a, b });
            Ok(())
        });
        methods.add_method("get_second", |_, this, idx: usize| {
            // How do I return a reference to MySecondUserData without cloning?
            Ok(this.1.get(idx).cloned())
        });
    }
}

impl LuaUserData for MySecondUserData {
    fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
        methods.add_method("get_a", |_, this, ()| Ok(this.a));
        methods.add_method("get_b", |_, this, ()| Ok(this.b.clone()));
    }
}
local my_userdata = MyUserData()

my_userdata:push_second(0, "Hello World!")

local my_second_userdata = my_userdata:get_second(0) -- This must be a reference to the userdata inside the vec, not a clone.
my_second_userdata:set_a(1)

assert(my_userdata:get_second(0):get_a() == 1)

Seefaaa avatar Feb 27 '24 21:02 Seefaaa