How does package and require work? - lua

I have a module named load_modbus.
This is how i require it:
driver_modbus = require "lua_plugin/load_modbus";
Before I require it, I have these code lines:
-- Include Paths
package.path = package.path .. ";./usr/lua/?.lua;./usr/lua/lua_modules/?.lua";
package.cpath = package.cpath .. ";./lib/?.so;./usr/lib/?.so";
How does the require work now?
Does it take the path which I gave to require, (lua_plugin/load_modbus) and place it instead of the ? ?
Am I correct that it will search for these files:
./usr/lua/lua_plugin/load_modbus.lua;
./usr/lua/lua_modules/lua_plugin/load_modbus.lua
./lib/lua_plugin/load_modbus.so;
./usr/lib/lua_plugin/load_modbus.so
It would be nice if someone can tell me if I am correct or not. Still try to understand how it works.

Short answer: Yes.
Require does not assume you give it a path, but a template. This is because lua can be used on systems that don't have an actual file system. If you give it a string like "/include/?.lua" and require "test" it will replace the "?" with the string you required and try to load "/include/test.lua".
You are mostly correct with the paths it will search, but keep in mind that if you do package.path = package.path .. <something> will just be appended to the standard search path, so it will not only search that path, but all the others too. If you only want to search one path, you'd have to do package.path = <your search path>
There is some more information on this at http://lua.org/manual/5.3
Consider reading that. It might also be interesting to you that lua caches the result of it's require calls, in case you didn't know that already.

Related

Require looks for .dll files instead of my modules?

So i've been trying to figure this out, im doing the following
main.lua:
package.path = io.popen("cd"):read'*all' -- to set the path the same as main.lua (for exporting)
local u = require("utilities") -- this is the line that dosent work
utilities.lua:
local u = {}
function u.GetService(s)
return require(tostring(s))
end
function u.Wait(s)
local ntime = os.clock() + s/10
repeat until os.clock() > ntime
end
function u.NPWait(s)
local ntime = os.time() + s
repeat until os.time() > ntime
end
return u
The error:
module 'utilities' not found:
Then here goes a search that DOES look in the correct folder, however it looks for .dll files
Require has never been something I've been good at, Sometimes I get it to work, sometimes it breaks like this, if someone can help me understand how to fix this then thank you, as this has been annoying me every so often
You're misunderstanding package.path.
Unlike the PATH variable used by windows and linux, in Lua you don't just tell it what directory to look in but also what the files should look like.
What you're doing is erasing the default search paths completely and replacing it with a broken path that won't find any files.
Generally speaking, to add a new directory to your path, you should add both C:\path\to\your\files\?.lua, and C:\path\to\your\files\?\init.lua, which are the two ways Lua loads modules by default.
You also shouldn't replace package.path, because you're keeping modules from being loaded elsewhere.
Your code should look somewhat like this:
local cd = io.popen("cd")
package.path = cd:read('*line') .. "\\?.lua;" .. package.path
cd:close()
The reason why it's still looking for DLL files is that package.cpath is separate, so you're not changing that.
require("utilities.lua") should work.
You have to specify how to get from the required name to the file. For example by adding a path and a file extension to it.
If you want to require c:\folder\script.lua with require("script") your package.path must contain something like c:\folder\?.lua where ? is replaced by the required name.
If you have your module in a folder with its name and let's say a init.lua for that module the path is c:\folder\?\init.lua
Just print the original package.path and see what's inside befor you overwrite it.
Refer to Lua Reference Manual 6.3 Modules: package.searchpath
A path is a string containing a sequence of templates separated by
semicolons. For each template, the function replaces each
interrogation mark (if any) in the template with a copy of name
wherein all occurrences of sep (a dot, by default) were replaced by
rep (the system's directory separator, by default), and then tries to
open the resulting file name.
For instance, if the path is the string
"./?.lua;./?.lc;/usr/local/?/init.lua" the search for the name foo.a will try to open the files ./foo/a.lua, ./foo/a.lc, and
/usr/local/foo/a/init.lua, in that order.

in lua (love2D), i want to import a library in a subfolder, the file in there will not find the next module it requires

So in lua, i want to import a module.
I want to have my "polygon" lib in a subfolder, so i reference it like this
local polygon = require('polygon.polygon')
however, it needs another module called 'delaunay', it cannot find it as it checks the main folder
Is there anyway short of editing my library, to get this to work? (some kind of ability to add search paths?)
Thanks
To know where to look for modules, Lua's require uses the variables package.path (.lua) and package.cpath (.so/.dll). You can change them in your program to look in the directory you have it in. For consistency's sake, you can look at their contents to know which OS-specific separator to use. For example:
local sep = package.path:find("\\") and "\\" or "/"
package.path = package.path .. ";." .. sep .. "polygon" .. sep .. "?.lua"
This would include ./polygon/?.lua into the search path, and a call to require "delaunay" would therefore have the require function look for ./polygon/delaunay.lua in addition to existing paths. Bear in mind that in require strings, . denotes a separator as far as file searching is concerned, so calling require "polygon.delaunay" in this scenario will mean searching for ./polygon/polygon/delaunay.lua.
From what I understand of your question, changing the package.path variable to include the path to where your delaunay library is stored would solve your issue, although to give a specific solution more information about your project and directory structure is required.
All what loaded into package.loaded can be load with require() because require() looks first in package.loaded...
-- Lua 5.3 ( lua -i )
> package.loaded.code=load(code.dump)()
> test=require('code')
> test
function: 0x565cb820
So you can use load() or loadfile('/path/to/your_code.lua') to do this. Another nice feature of this method is to load dumped code...
> package.loaded.shell=loadfile('shell.bin')
> shell=require('shell')
> shell('cat shell.bin')
uaS�
�
xV(w#F#�d�#��F�#G���d#��F�#G���d#&�typestringoexecute
/bin/bash>
In any way, it appears that you will have to deal with the subfolders explicitly.
As in, either the module polygon will have to import delaunay as polygon.delaunay.
Or module names will have to be appended to package.path so that lua could search through subfolders for filenames:
package.path=package.path..";./polygon/?.lua"
More info is here.
It is pointed out in comments, you'd probably want to ensure that path concatenation happens only once.
Also, one should be wary of name shadowing.
Finally, while we are at stirring up the past, a pretty nifty trick to solve the issue was proposed here five years before the question.

how to load modules in different folders

I have following folder structure
--folder1
------main.lua
------sub_folder
---------func1.lua
--folder2
------func2.lua
I want to load func1.lua and func2.lua in main.lua by require command
PS:what does the init.lua in a folder do
In vanilla lua, you'd load them like this:
local func1 = loadfile "sub_folder/func1.lua"
local func2 = loadfile "../folder2/func2.lua"
See: Pil Chapter 8
If you're using Lua embedded in some other application (i.e, a game, software, etc.), then you need to let us know what this is, or we can't help you. This goes for your P.S question as well. But generally, init.lua is usually the first file to be executed, i.e, it'll load other files, etc.
The func1.lua is easily loaded via
require 'sub_folder.func1'
because sub_folder is in the same folder as main.lua.
For func2.lua, there is no way to tell require to search "one level up", so you must tell Lua how to find the required modules. This can be done at least two ways:
via LUA_PATH environment variable:
append path/to/folder2/?.lua to it, then main.lua can do require "func2".
OR append path/to/parent-of-folder2/?.lua to it, then main.lua can do require "folder2.func2".
by editing package.path in your script:
package.path = package.path .. ';../?.lua'
require 'func2'
or
package.path = package.path .. ';../../?.lua'
require 'folder2.func2'
The first method is more "permanent" since the setting is in the OS environment; it will work even if you move folder1 to some other place on your system, without moving folder2. The second method is dynamic so it will work regardless of where you place your folder structure, i.e., if folder2 is always sibling folder of folder1 the method 2 works, method 1 fails (or requires that you edit the LUA_PATH).

How to navigate with .lua to a directory above

I have something like this.
/config.lua
/client/init.lua
How can I include the config.lua with include() or dofile()?
Lg
You can (and probably should) do this with require by adding ../?.lua to package.path, like so:
package.path = package.path .. ";../?.lua"
require "config"
See the require and package.path docs for more info.
You're on the right track with dofile. (However, there is no include function in Lua.) As you may have noticed, you can't do this with require:
local cfg = require'../config'
require typically works from the directory of the initial script in a one-way direction, and any required modules which require their own modules must use relative names from that starting point to work properly.
I.e., if you have the following structure:
--+ main.lua requires 'lib.test1'
+-- lib/test1.lua requires 'test2'
+-- lib/test2.lua
test1.lua will fail to require test2 because it cannot be found from the initial directory. lib.test2 is the appropriate module name here. I'm not sure if there are any good patterns for this, short of writing your own stateful require, but it's helpful to know about when writing library code.
Perhaps it's a bad sign when it comes to this.
Going back to the question, you could make an exemption for your config file in package.loaded. This is effectively loading it manually:
package.loaded.config = dofile'../config.lua'
-- ...
local cfg = require'config'

Lua Require function on a full path name

I need to call the require on a lua file that will not always be in the same place. I was trying to call require on the full path name but that doesn't seem to be working either. I even tried replacing one of my working normal requires with a correct full path name to the same file
example changing
require "foo"
to
require "C:\Users\Me\MyLuaProject\foo"
but when i switched it to the full path name it could no longer find it. So I am wondering if you can even call require on a full path and if not how would i achieve the same result differently?
If you just need to load a file, use dofile, which takes a path:
dofile("C:\\Users\\Me\\MyLuaProject\\foo")
Add the directory containing the file to package.path:
package.path = package.path .. ";C:\\Users\\Me\\MyLuaProject"
require "foo"
You can also add it to the LUA_PATH environment variable, but this is probably less easy to modify on the fly.
A common pattern for modules is to have abc.lua and abc/xyz.lua; to require files in a subdirectory like that, use the following:
require "abc"
require "abc.xyz"

Resources