2
votes

I have a Lua module, which returns an export table (i.e. not using the deprecated module directive). Also, I have a script which wants to load that module via "require" function. Now I load both files to lua state from C code like this:

luaL_loadstring(lua, someScript);
lua_pcall(lua, 0, LUA_MULTRET, 0);
luaL_loadstring(lua, someModule);
lua_pcall(lua, 0, LUA_MULTRET, 0);

The require call fails, because it looks for the file, rather than the code, which is already loaded. Is it possible to somehow require someModule from someScript in this situation?

3
My questions and request for clarifications didn't fit in a comment so put in a question, I will extend that answer based on your clarifications (which BTW you should put in your question, not in comments) - Oliver

3 Answers

1
votes

The documentation for require contains all the information you need to make this work. Specifically it tells you what methodology the require function uses to find the code being requested. Even more specifically the first sentence about package.loaded is what you likely want to be paying attention to.

Documentation from above link:

Loads the given module. The function starts by looking into the package.loaded table to determine whether modname is already loaded. If it is, then require returns the value stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module.

To find a loader, require is guided by the package.loaders array. By changing this array, we can change how require looks for a module. The following explanation is based on the default configuration for package.loaders.

First require queries package.preload[modname]. If it has a value, this value (which should be a function) is the loader. Otherwise require searches for a Lua loader using the path stored in package.path. If that also fails, it searches for a C loader using the path stored in package.cpath. If that also fails, it tries an all-in-one loader (see package.loaders).

Once a loader is found, require calls the loader with a single argument, modname. If the loader returns any value, require assigns the returned value to package.loaded[modname]. If the loader returns no value and has not assigned any value to package.loaded[modname], then require assigns true to this entry. In any case, require returns the final value of package.loaded[modname].

If there is any error loading or running the module, or if it cannot find any loader for the module, then require signals an error.

0
votes

For clarity let's name things: module A returns an export table; script B is a string that requires module A, and I'll assume B returns nothing. Also you want to do the following:

load script B (via luaL_loadstring): puts chunk on stack
run chunk for script B (via lua_pcall): puts whatever B returns on stack
load module A (via luaL_loadstring): puts chunk on stack
run module A (via lua_pcall): puts whatever A returns on stack

Firstly, module A is a file so presumably you've loaded the contents of A into a string.

You say that your issue is that require, called in script B, fails. There could be several reasons, such as B does require 'moduleA', but moduleA.lua is not found in LUA_PATH folders.

So:

  • print the part of B that requires A so we can see the code
  • verify that LUA_PATH is such that moduleA.lua can be found

Once the above is confirmed to be ok, we can look at your C API calls, but I doubt those are the issues.

0
votes

If someModule uses require"modname" then try this code:

lua_getglobal(lua, "package");
lua_getfield(lua, -1, "loaded");
luaL_loadstring(lua, someScript);
lua_pcall(lua, 0, 1, 0);
lua_setfield(lua, -2, modname);
luaL_loadstring(lua, someModule);
lua_pcall(lua, 0, LUA_MULTRET, 0);