Git Product home page Git Product logo

Comments (8)

jugglerchris avatar jugglerchris commented on July 19, 2024

Yes, require is quite flexible - you can just store your http table in packaged.loaded["http"], and require will find it.

https://www.lua.org/manual/5.4/manual.html#pdf-require

from rlua.

Yakiyo avatar Yakiyo commented on July 19, 2024

Yes, require is quite flexible - you can just store your http table in packaged.loaded["http"], and require will find it.

https://www.lua.org/manual/5.4/manual.html#pdf-require

How do i go about implementing it? i tried the following:

let globals = ctx.globals();
let packaged: rlua::Table = globals.get("packaged").unwrap_or(ctx.create_table()?);
let loaded: rlua::Table = packaged.get("loaded").unwrap_or(ctx.create_table()?);
loaded.set("http", http)?;
packaged.set("loaded", loaded)?;
globals.set("packaged", packaged)?;

yet when running the following snippet

http = require("http")

-- define client
local client = http.client()

-- client get request
local res = client:get("https://httpbin.org/get")
print("res 1")
print(res:body())

-- client post request
local res2 = client:post("https://httpbin.org/post", "hi")
print("res 2")
print(res2:body())

-- client do_request
local request = http.request("GET", "https://httpbin.org/get")
local res3 = client:do_request(request)
print("res 3")
print(res3:body())

print("status equality")
print(res:status() == res3:status())

-- top level get function 
-- equivalent to creating a client and then doing a get request
local get_resp = http.get("https://httpbin.org/get")
print("get resp")
print(get_resp:body())

i get this error

RuntimeError("[string \"?\"]:1: module 'http' not found:\n\tno field package.preload['http']\n\tno file '/usr/local/share/lua/5.4/http.lua'\n\tno file '/usr/local/share/lua/5.4/http/init.lua'\n\tno file '/usr/local/lib/lua/5.4/http.lua'\n\tno file '/usr/local/lib/lua/5.4/http/init.lua'\n\tno file './http.lua'\n\tno file './http/init.lua'\nstack traceback:\n\t[C]: in ?\n\t[C]: in function 'require'\n\t[string \"?\"]:1: in main chunk")

from rlua.

azdle avatar azdle commented on July 19, 2024

You've (both) got a small typo, you're meaning to use package.loaded (not 'packaged').

Though, that is technically not the way you're supposed to do it. As https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded says:

This variable is only a reference to the real table; assignments to this variable do not change the table used by require. The real table is stored in the C registry (see §4.3), indexed by the key LUA_LOADED_TABLE, a string.

(Though, in my experience, despite what it says, it does (at least sometimes) work.)

The proper™ way to make a custom set of packages for require is to create a package.searchers entry: https://www.lua.org/manual/5.4/manual.html#pdf-package.searchers

from rlua.

jugglerchris avatar jugglerchris commented on July 19, 2024

Oops, thanks @azdle for the correction, I did indeed mean package.loaded.

@Yakiyo you don't need to re-set packaged/loaded, you're working with references to the original table. Here's a brief working example:

    Lua::new().context(|lua| {
        let my_mod = lua.create_table().unwrap();
        let hello = lua.create_function(|_, (): ()| {
            println!("Hello, world!");

            Ok(())
        }).unwrap();
        my_mod.set("hello", hello).unwrap();

        let globals = lua.globals();
        let package: Table<'_> = globals.get("package").unwrap();
        let package_loaded: Table<'_> = package.get("loaded").unwrap();
        package_loaded.set("my_mod", my_mod).unwrap();

        let () = lua.load(
            r#"
               local my_mod = require('my_mod')
               my_mod.hello()
            "#,
            )
            .eval()
            .unwrap();
    });

If you're the code setting up the application, and you're happy to build your modules immediately (i.e. it's not expensive), then I don't see any reason not to do it this way. If you let random Lua code run before then, then package.loaded may have been changed to point to something completely different.

I agree that accessing it via the registry lua.named_registry_value(rlua::ffi::LUA_LOADED_TABLE) would be more correct, though ffi is currently private in rlua. You could assume it won't change (I don't think it can change within a release), so you could get away with using b"_LOADED\0" (the value in Lua 5.3/5.4).

Using package.searchers is probably better for more involved cases, e.g. if you have many modules or some are expensive to initialise, but IMO is overkill when adding a small module or three in a small application.

from rlua.

Yakiyo avatar Yakiyo commented on July 19, 2024

Oops, thanks @azdle for the correction, I did indeed mean package.loaded.

@Yakiyo you don't need to re-set packaged/loaded, you're working with references to the original table.

yeah i figured that, i initially did it cz since packaged was nil, i thought i had to reset it. using package.loaded works fine for me. i was just trying to write some extension modules that can be used in rlua (repo). i dont suppose there could be a way to use package.searchers for that. But just for reference, how would u do that with package.searchers? whats the function signature for it?

from rlua.

Yakiyo avatar Yakiyo commented on July 19, 2024

And another question. i have a lua file, which contains 3/4 different functions. is it in any way possible for me to take and call those functions from the rust side, outside of Lua::context? the premise of this is, ive got extensions written in lua, where all of them export, for example two funcs, add and sub. i'll load each lua file with a new Lua instance, and then eval them? but then how do i keep a reference to those funcs, so that i can invoke em when i need. instead of calling lua.context and doing something else.

from rlua.

jugglerchris avatar jugglerchris commented on July 19, 2024

But just for reference, how would u do that with package.searchers? whats the function signature for it?

According to https://www.lua.org/manual/5.4/manual.html#pdf-package.searchers the searcher is called with the module name, and if successful returns a "loader" function; calling that loader function returns the module. Which sounds complicated for one module, but makes a lot of sense if the searcher is doing something like looking in the filesystem, and returns a function to read and compile that file.

but then how do i keep a reference to those funcs, so that i can invoke em when i need. instead of calling lua.context and doing something else.

You can't call the Lua functions outside of lua.context - this is part of how rlua ensures Rust safety. What you can do is use create_registry_value to get back a RegistryKey which you can store outside of the context function. You can then get the Lua value back efficiently with registry_value later (but still in the context call).

from rlua.

Yakiyo avatar Yakiyo commented on July 19, 2024

But just for reference, how would u do that with package.searchers? whats the function signature for it?

According to https://www.lua.org/manual/5.4/manual.html#pdf-package.searchers the searcher is called with the module name, and if successful returns a "loader" function; calling that loader function returns the module. Which sounds complicated for one module, but makes a lot of sense if the searcher is doing something like looking in the filesystem, and returns a function to read and compile that file.

but then how do i keep a reference to those funcs, so that i can invoke em when i need. instead of calling lua.context and doing something else.

You can't call the Lua functions outside of lua.context - this is part of how rlua ensures Rust safety. What you can do is use create_registry_value to get back a RegistryKey which you can store outside of the context function. You can then get the Lua value back efficiently with registry_value later (but still in the context call).

Aight understood. thanks for the help. then ill go ahead and close this as completed.

from rlua.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.