Calling back to a main file from a dofile in lua - lua

Say i have two files:
One is called mainFile.lua:
function altDoFile(name)
dofile(debug.getinfo(1).source:sub(debug.getinfo(1).source:find(".*\\")):sub(2)..name)
end
altDoFile("libs/caller.lua")
function callBack()
print "called back"
end
doCallback()
The other called caller.lua, located in a libs folder:
function doCallback()
print "performing call back"
_G["callBack"]()
end
The output of running the first file is then:
"performing call back"
Then nothing more, i'm missing a line!
Why is callBack never getting executed? is this intended behavior, and how do i get around it?
The fact that the function is getting called from string is important, so that can't be changed.
UPDATE:
I have tested it further, and the _G["callBack"] does resolve to a function (type()) but it still does not get called

Why not just use dofile?
It seems that the purpose of altDoFile is to replace the running script's filename with the script you want to call thereby creating an absolute path. In this case the path for caller.lua is a relative path so you shouldn't need to change anything for Lua to load the file.
Refactoring your code to this:
dofile("libs/caller.lua")
function callBack()
print "called back"
end
doCallback()
Seems to give the result you are looking for:
$ lua mainFile.lua
performing call back
called back
Just as a side note, altDoFile throws an error if the path does not contain a \ character. Windows uses the backslash for path names, but other operating systems like Linux and MacOS do not.
In my case running your script on Linux throws an error because string.find returns nill instead of an index.
lua: mainFile.lua:2: bad argument #1 to 'sub' (number expected, got nil)
If you need to know the working path of the main script, why not pass it as a command line argument:
C:\LuaFiles> lua mainFile.lua C:/LuaFiles
Then in Lua:
local working_path = arg[1] or '.'
dofile(working_path..'/libs/caller.lua')

If you just want to be able to walk back up one directory, you can also modify the loader
package.path = ";../?.lua" .. package.path;
So then you could run your file by doing:
require("caller")

dofile "../Untitled/SensorLib.lua" --use backpath librarys
Best Regards
K.

Related

"function arguments expected near 'levelc'" when using LOVE

I'm currently trying to make a level loading system for a game.
function love.filedropped(file)
ofile=io.open(file:getFilename(),"r")
io.input(ofile)
file:close
levelc=io.read()
for i=1,levelc do
levels[i]=io.read()
print levels[i]
end
levelc should be the first line of the file, and file:getFilename is the file to open (path included) the project gives an error message on startup, and i've used a similar structure before, but for an output. The error is at line 30, which is the levelc=io.read().
I've tried changing the name of the file pointer (it was "f" before, now "ofile") and i've tried using io.read("*l") instead of io.read() but same result.
EDITS:
-this is a love.filedropped(file)
-i need to open other files from a .txt later and i don't really understand how do do that
The parameter given by love.filedropped is a DroppedFile.
In your case helpful could be File:lines().
For example:
function love.filedropped(file)
-- Open for reading
file:open("r")
-- Iterate over the lines
local i = 0
for line in file:lines() do
i = i + 1
levels[i] = line
print(i, levels[i]) -- Notice the parentheses missing in your code
end
-- Close the file
file:close()
end
Notice that love2d usually only allows reading/writing files within the save or working directory. Dropped files are an exception.
Unrelated to this answer but things I noticed in your code:
Use locals, oFile should be local
file:close() required parentheses as its a function call
Same for the print
The filedropped callback has no end
You mentioned reading other files too, to do so, you can either:
Use love.filesystem.newFile and a similar approach as before
The recommended one-liner love.filesystem.lines

luaL_loadbufferx returns syntaxerrors

I'm working on a personal project and I'm trying to get Lua to work on my embedded device.
I have my own simple file system that works with the the flash drive, and now I'm trying to use modules for the lua scripts that I run on the device.
I have edited linit.c, to make it also load the modules that are existing in the flash drive, and it works for a few modules, but for most of them it just gives me a syntax error when it parses the contents of the module. I have a lua interpreter running on my Windows machine and the code I'm writing is syntactically correct and works, and the Lua API that I use is of the same version 5.4 on the device.
These are the arguments I pass to
luaL_loadbufferx(L, luaCFunction, sizeOfModule, moduleName, "t")
where, L is the lua state, luaCFunction is the lua module wrapped in a C-style return statement, sizeOfModule, moduleName and t is selfexplanatory.
Right now luaL_loadbufferx is called in a loop for every module in my flash-drive, I have overwritten the openf function from the Lua API for these external modules.
This below is one of the examples of a module that gives me
"Syntax Error: PANIC, unprotected error in call to Lua API
[string "module"]:3: '(' expected near 'writeobj'"
File: module.lua
Contents:
function writeobj()
print('Hello World')
end
File: run.lua
Contents:
require ('module')
writeobj()
Does anyone know why this happens or did I not provide sufficient information? Please let me know.
The problem was that I thought the modules passed to the buffer had to be of the LuaToC form, i.e. "return { ...luamodule...}", but changing it to pass the module only to loadbuffer was sufficient enough because it covers the case of it not being in a C style return format.

Find name and location of Lua executeable

I need to find the name of the Lua executeable from within a Lua script as it sets up a task for later execution.
Using arg I can find out the name, however this becomes un reliable if options are used. For example, if no arguments are used running within a script print( arg[-1]) would print lua53. However if options are used they would be printed instead, such as -i, and to get the exe I would have change the line to print( arg[-2]).
What method will reliably get the name of the lua binary?
Try this
i=0
repeat i=i-1 until arg[i]==nil
i=i+1
print(i,arg[i])

Luac don't work with one script

I have embedded lua and I want precompile my script. For that, I call the main of luac (with argc the number of file is 1). My problem is on the function doargs of luac. I don't understand the use of the variable i. Because when I use one script. The result of i after the doargs function is 1. And in the main function we have argc -= i after. And so argc = 0 and I have a error "no file". Any idea ?
luac is meant to be a command line utility for compiling .lua files. This expected usage is the reason why you're getting an error.
When you start an executable the OS passes the name of the program as its first argument (argv[0]). The luac main function assumes it is being called by the OS, so it expects that there will always be at least one argument and its argv[0] will be the name of the executable.
For this reason doargs starts its for loop at 1 and will always ignore that first (0th) argument. It returns how many options it has processed, which is also the offset of the first filename in the argv array. The main function uses this to know where the list of files starts.
If you really want to use the main function to precompile your scripts, then supply an extra dummy argument at the beginning of your argument array and list your files after that. Preferably you should use luac from the command line and supply an output file where the precompiled script will be stored like this:
luac -o outputFile script.lua
Alternatively, take a look at chapter 8 of Programming in Lua (Compilation, Execution, and Errors) for a pure Lua solution, or the the luaL_dofile, luaL_dostring, lua_dump, and lua_load functions in the Reference Manual for a C API solution.

Getting return status AND program output

I need to use Lua to run a binary program that may write something in its stdout and also returns a status code (also known as "exit status").
I searched the web and couldn't find something that does what I need. However I found out that in Lua:
os.execute() returns the status code
io.popen() returns a file handler that can be used to read process output
However I need both. Writing a wrapper function that runs both functions behind the scene is not an option because of process overhead and possibly changes in result on consecutive runs. I need to write a function like this:
function run(binpath)
...
return output,exitcode
end
Does anyone has an idea how this problem can be solved?
PS. the target system rung Linux.
With Lua 5.2 I can do the following and it works
-- This will open the file
local file = io.popen('dmesg')
-- This will read all of the output, as always
local output = file:read('*all')
-- This will get a table with some return stuff
-- rc[1] will be true, false or nil
-- rc[3] will be the signal
local rc = {file:close()}
I hope this helps!
I can't use Lua 5.2, I use this helper function.
function execute_command(command)
local tmpfile = '/tmp/lua_execute_tmp_file'
local exit = os.execute(command .. ' > ' .. tmpfile .. ' 2> ' .. tmpfile .. '.err')
local stdout_file = io.open(tmpfile)
local stdout = stdout_file:read("*all")
local stderr_file = io.open(tmpfile .. '.err')
local stderr = stderr_file:read("*all")
stdout_file:close()
stderr_file:close()
return exit, stdout, stderr
end
This is how I do it.
local process = io.popen('command; echo $?') -- echo return code of last run command
local lastline
for line in process:lines() do
lastline = line
end
print(lastline) -- the return code is the last line of output
If the last line has fixed length you can read it directly using file:seek("end", -offset), offset should be the length of the last line in bytes.
This functionality is provided in C by pclose.
Upon successful return, pclose() shall return the termination status
of the command language interpreter.
The interpreter returns the termination status of its child.
But Lua doesn't do this right (io.close always returns true). I haven't dug into these threads but some people are complaining about this brain damage.
http://lua-users.org/lists/lua-l/2004-05/msg00005.html
http://lua-users.org/lists/lua-l/2011-02/msg00387.html
If you're running this code on Win32 or in a POSIX environment, you could try this Lua extension: http://code.google.com/p/lua-ex-api/
Alternatively, you could write a small shell script (assuming bash or similar is available) that:
executes the correct executable, capturing the exit code into a shell variable,
prints a newline and terminal character/string onto standard out
prints the shell variables value (the exit code) onto standard out
Then, capture all the output of io.popen and parse backward.
Full disclosure: I'm not a Lua developer.
yes , your are right that os.execute() has returns and it's very simple if you understand how to run your command with and with out lua
you also may want to know how many variables it returns , and it might take a while , but i think you can try
local a, b, c, d, e=os.execute(-what ever your command is-)
for my example a is an first returned argument , b is the second returned argument , and etc.. i think i answered your question right, based off of what you are asking.

Resources