Skip to content

Implementing UserData and FromLua for non Copyable/Clonable structs #599

@oezingle

Description

@oezingle

Hi All,

I must admit I'm quite new to both Rust and mlua. I'm familiar with C/C++ and read the Rust documentation book up to chapter 7. After deciding that I should just get my toes wet.

I've started my first project - a Lua module port of wasmtime, with the eventual goal of writing a loader to integrate WASM modules with lua. I could skip a bunch of steps here by writing the loader entirely in Rust, but I was hoping to port the wasmtime API so I could provide a WebAssembly API in Lua similar to JavaScript. However, I'm getting very stuck with the (absurdly underdocumented IMO) UserData and FromLua traits.

Here's my naive approach to get the wasmtime::Engine struct to be accessible from the Lua side.

use mlua::{
    Lua,
    
    UserData, FromLua,
    
    Table, Function, Value,
};
use mlua::prelude::LuaResult;

use wasmtime::Engine;

#[derive(Copy)]
pub struct LuaEngine {
    internal: Engine,
}

impl LuaEngine {
    fn default () -> LuaResult<LuaEngine> {
        return Ok(LuaEngine {
            internal: Engine::default(),
        });
    }

    pub fn get (&self) -> &Engine {
        return &self.internal;
    }
}

impl UserData for LuaEngine {
}

impl FromLua for LuaEngine {
    fn from_lua(value: Value, _: &Lua) -> LuaResult<Self> {
        match value {
            Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
            _ => unreachable!(),
        }
    }
}

// I'm using a table here because I'd prefer the module to publish 
// 'structs-as-tables' when possible, in keeping with lua's style
pub fn register_engine (lua: &Lua) -> LuaResult<Table> {
    let engine = lua.create_table()?;

    engine.set("default", Function::wrap(LuaEngine::default))?;

    return Ok(engine);
}

Compiling causes a build error - wasmtime::Engine does not implement std::marker::Copy. I'm sort of lost at this point. I need LuaEngine to implement FromLua because of wasmtime::Module::from_file(engine: &Engine, path: String) (and its eventual Lua counterpart).

How can I get around this restriction? I want a LuaEngine instance to essentially be a reference to a wasmtime::Engine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions