Loading in Lua Modules via Require (TLC) - lua

I'm trying to use https://github.com/aptiva/TLC
I try:
$ echo $LUA_PATH; echo "====="; find .; echo "====="; luajit-2.0.0-beta10 examples/window.lua
I get:
?;?.lua;./?/init.lua
=====
.
./examples
./examples/talkingcomputer.lua
./examples/window.lua
./lst
./objc
./objc/BridgeSupport.lua
./objc/dispatch.lua
./objc/init.lua
./README.md
=====
luajit-2.0.0-beta10: error loading module 'objc' from file 'objc':
cannot read objc: Is a directory
stack traceback:
[C]: ?
[C]: in function 'require'
examples/window.lua:5: in main chunk
[C]: ?
My question: what am I doing wrong? How do I load in the objc module?
Thanks!

Add ./?/init.lua to LUA_PATH.

Some further explanation on why the accepted solution works.
When a module is required, Lua uses environment variable LUA_PATH to find the location of the required module. The special symbol '?' is a wildcard that matches any string, thus when require("module") and LUA_PATH="?;./?.lua", Lua will search for 'module' and 'module.lua' in the current directory.
In the question above LUA_PATH was originally defined as:
LUA_PATH="?;?.lua;"
Once the solution was posted, the user added ./?/init.lua at the end of LUA_PATH, however it didn't work. The reason why it didn't work was that when Lua tries to solve require('objc') objc matches the first entry in LUA_PATH (?), and objc is a directory, thus the error.
The solution is to add ./?/init.lua at the beginning of LUA_PATH:
LUA_PATH="./?/init.lua;?.lua;?;"
With regard to LUA_PATH, it's important to notice that unlike environment variable PATH, directories are separated by semicolon (";"). Another way of specifying what directories to search from, it's using Lua variable package.path (inside a Lua file):
package.path = "./?/init.lua;"..package.path
local objc = require("objc")

Related

Lua require does not work but file is in the trace

I'm trying to require files in Lua, in one case it is working, but when I want to simplify the requirements in updating the LUA PATH the file is not found, but it is in the trace!
To reproduce my require problem I did the test with the package.searchpath function, which takes the required key and the Lua path in arguments.
So the code :
print('MY LUA PATH')
local myLuaPath = "?;?.lua;D:\\Projets\\wow-addon\\HeyThere\\?;D:\\Projets\\wow-addon\\HeyThere\\src\\HeyThere\\?;D:\\Projets\\wow-addon\\HeyThere\\test\\HeyThere\\?"
print(myLuaPath)
print('package search core.add-test')
print(package.searchpath('core.add-test', myLuaPath))
print('package search test.HeyThere.core.add-test')
print(package.searchpath('test.HeyThere.core.add-test', myLuaPath))
The result :
MY LUA PATH
?;?.lua;D:\Projets\wow-addon\HeyThere\?;D:\Projets\wow-addon\HeyThere\src\HeyThere\?;D:\Projets\wow-addon\HeyThere\test\HeyThere\?
package search core.add-test
nil no file 'core\add-test'
no file 'core\add-test.lua'
no file 'D:\Projets\wow-addon\HeyThere\core\add-test'
no file 'D:\Projets\wow-addon\HeyThere\src\HeyThere\core\add-test'
no file 'D:\Projets\wow-addon\HeyThere\test\HeyThere\core\add-test'
package search test.HeyThere.core.add-test
test\HeyThere\core\add-test.lua
So the first try with 'core.add-test' should work with the 'D:\Projets\wow-addon\HeyThere\test\HeyThere\?' value in the path but fails...
In the trace, there is the file I want!
no file 'D:\Projets\wow-addon\HeyThere\test\HeyThere\core\add-test'
But with the same LUA PATH but starting in a parent folder the file is found... Second test with 'test.HeyThere.core.add-test' found from the 'D:\Projets\wow-addon\HeyThere\?'
-> test\HeyThere\core\add-test.lua
Can someone explains to me why it doesn't work the first time?
EDIT :
My current directory is D:\Projets\wow-addon\HeyThere
My lua.exe is in D:\Projets\wow-addon\HeyThere\bin\lua but is added to my PATH variable (I'm on Windows)
I set the LUA_PATH environment variable and execute
lua "test\test-suite.lua" -v
The code inside test-suite.lua is the test code described above
As #EgorSkriptunoff suggested, adding file extansion in the path resolve the problem...
Ex:
Wrong path D:\Projets\wow-addon\HeyThere\?
Good path D:\Projets\wow-addon\HeyThere\?.lua
The extension should be in the path variable because in the require the dot is replace and used as a folder separator.

How to require a shared object file (nuklear.so) from a subdirectory in Love2D?

For a small game, I'm trying out the love-nuklear library to create UIs. I've successfully built the .so by following the exact instructions provided by the author, see this section.
When nuklear.so is placed in the same directory as my main.lua file, nuklear = require('nuklear.so') imports the library correctly, and is accessible when I run $ love ..
However for better organization, I've decided to move nuklear.so into a subdirectoy lib/, where other lua modules are also imported. But now in main.lua, when using nuklear = require('lib.nuklear'), then running $ love . in the project root directory, the following error is produced:
Error: error loading module 'lib.nuklear' from file './lib/nuklear.so':
./lib/nuklear.so: undefined symbol: luaopen_lib_nuklear
stack traceback:
[string "boot.lua"]:637: in function <[string "boot.lua"]:633>
[C]: at 0x7ff27837fc00
[C]: in function 'require'
main.lua:4: in main chunk
[C]: in function 'require'
[string "boot.lua"]:475: in function <[string "boot.lua"]:311>
[C]: in function 'xpcall'
[string "boot.lua"]:645: in function <[string "boot.lua"]:639>
[C]: in function 'xpcall'
How should I correctly relocate my shared object from the project root directory to its lib/ subdirectory?
By default when loading a C library, Lua looks for a function in the library named luaopen_x, where x is the module name with . replaced with _ (and with some other transformations), and runs it. (See the documentation for package.searchers.) In this case the module name lib.nuklear results in the function name luaopen_lib_nuklear. But the function is actually named luaopen_nuklear, so Lua doesn't find it and can't load the library.
To fix this, you can add ./lib/?.so to package.cpath before loading the library with require "nuklear": package.cpath = package.cpath .. ";./lib/?.so". Then Lua will look for luaopen_nuklear in ./lib/nuklear.so. This will allow you to load other .so libraries in that directory.
Getting the source code of nuklear.so and renaming luaopen_nuklear to luaopen_lib_nuklear and recompiling would also work, but would be kind of silly and wouldn't solve the problem for other C libraries in the same directory.

Lua 5.3 thinks socket.lua doesn't exist in a directory where it actually does exist

Here's a screenshot:
https://drive.google.com/open?id=0B4Dqo44FM648VTVKVzBKSERldGc
I would like to have fun contributing to the development of an open source game but this problem is preventing me from doing this.
My LuaRocks install is configured for Lua 5.3 and is set to use MinGW's build tools. My OS is Windows 10 64 bit.
My Lua 5.3.2 binaries were provided by this website (lua-5.3.2_Win64_bin.zip).
If you have an idea for a possible cause please post it.
You have to resolve environment variables manually:
os.getenv (varname)
Returns the value of the process environment variable varname, or nil
if the variable is not defined.
So, in your case you need to obtain the %APPDATA% path first:
os.getenv("APPDATA")
Returns: C:\Users\USERNAME\AppData\Roaming
When searching for packages to load, Lua uses a pre-defined list of folders to search in. This list is defined in package.path which is a semicolon-delimited (;) string. To add a new folder, you must append it's path to package.path:
package.path = package.path .. ";" .. NEWFOLDER .. "\\?.lua"
Finally, your complete solution is this:
package.path = package.path .. ";" .. os.getenv("APPDATA") .. "\\luarocks\\share\\lua\\5.3\\?.lua"
local s = require("socket")
"Lua does not expand environment variable references in package.path, so %APPDATA% won't work. You need the real path. The LuaRocks installation script should have said that: "Note that the %APPDATA% element in the paths above is user specific and it MUST be replaced by its actual value." - siffiejoe

How to structure internal dependencies in a Lua library?

I'm struggling to figure out how to structure and then use internal dependencies in a Lua library I'm writing.
I've defined my library like this:
./alib.lua
./alib/adependency.lua
And the code:
-- File: ./alib.lua
local ad = require "alib.adependency"
module( "alib")
return {}
-- File: ./alib/adependency.lua
module( "adependency" )
return {}
This works a treat:
$ lua alib.lua
<no output>
Now let's "add" this library into another app:
./anapp.lua
./lib/alib.lua
./lib/alib/adependency.lua
And the new code:
-- File: ./anapp.lua
local alib = require "lib.alib"
local print = print
module( "anapp")
print "Hello"
Try to run it:
$ lua anapp.lua
lua: ./lib/alib.lua:2: module 'alib.adependency' not found:
no field package.preload['alib.adependency']
no file './alib/adependency.lua'
no file '/usr/local/share/lua/5.1/alib/adependency.lua'
no file '/usr/local/share/lua/5.1/alib/adependency/init.lua'
no file '/usr/local/lib/lua/5.1/alib/adependency.lua'
no file '/usr/local/lib/lua/5.1/alib/adependency/init.lua'
no file '/usr/share/lua/5.1/alib/adependency.lua'
no file '/usr/share/lua/5.1/alib/adependency/init.lua'
no file './alib/adependency.so'
no file '/usr/local/lib/lua/5.1/alib/adependency.so'
no file '/usr/lib/x86_64-linux-gnu/lua/5.1/alib/adependency.so'
no file '/usr/lib/lua/5.1/alib/adependency.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
no file './alib.so'
no file '/usr/local/lib/lua/5.1/alib.so'
no file '/usr/lib/x86_64-linux-gnu/lua/5.1/alib.so'
no file '/usr/lib/lua/5.1/alib.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
[C]: in function 'require'
./lib/alib.lua:2: in main chunk
[C]: in function 'require'
anapp.lua:2: in main chunk
[C]: ?
Oh dear. Now I make a manual edit inside the library:
-- File: ./lib/alib.lua
-- local ad = require "alib.adependency" -- Doesn't work
local ad = require "lib.alib.adependency" -- Works
module( "alib")
return {}
And it works:
$ lua anapp.lua
Hello
It seems that Lua's require() relates paths relative to the ultimate script being run by Lua, not the script in which the require() is called.
Surely you don't have to manually fix the internal paths require()d inside of a Lua library every time you add one to your project... And I don't see how this can work from a unit test perspective either. What am I doing wrong?
I think the cleanest solution is to leave your library as it was, and then make whomever is using your library responsible for configuring the package.path correctly. In your setup that means the application should add the lib folder to the path:
package.path = './lib/?.lua;' .. package.path
See also related questions like Is there a better way to require file from relative path in lua as well as the manual for more about the path.

Lua require doesn't work on directories

I have been given some skeleton code for an assignment from my professor in lua. The code has several require statements that add packages to the current directory. The problem I am having is that many of these require statements are not requiring a .lua file, they require a directory containing many lua files. For instance, I have a directory qtwidget with a single file in it: init.lua
In the skeleton code, this package is referenced like this:
local w = qtwidget.newwindow(width,height,"Energy surface")
So that's all fine and dandy, but when I run the skeleton code I get the following error:
dofile('/data/mar608/BigData/src/optim/demo2.lua')
error loading module 'qttorch' from file '/usr/local/pkg/torch/share/torch/lua/qttorch':
cannot read /usr/local/pkg/torch/share/torch/lua/qttorch: Is a directory
stack traceback:
[C]: ?
[C]: in function 'require'
/data/me/BigData/src/optim/demo2.lua:36: in main chunk
[C]: in function 'dofile'
[string "dofile('/data/mar608/BigData/src/optim/demo..."]:1: in main chunk
[C]: ?
What's going on? Why doesn't lua understand this require statement? Is there any way I need to chance my package.path variable that will solve this problem? I need to be able to do this for many directories (i.e. specify the directories name and have lua load all it's files into a single name to be referenced later)
1) Do you have /usr/local/pkg/torch/share/torch/lua/qttorch/init.lua ?
2) Do you have .../?/init.lua entry in package.path ?
Example: /usr/local/share/lua/5.2/?.lua;/usr/local/share/lua/5.2/?/init.lua;/usr/local/lib/lua/5.2/?.lua;/usr/local/lib/lua/5.2/?/init.lua;./?.lua.

Resources