Find name and location of Lua executeable - lua

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])

Related

Assign bash output to variable in .lua script

I would like to assign output of a bash command to a variable in .lua script. Is it possible?
For instance, something similar to:
var = `ps uax | grep myprocess`
Yes, you need to use io.popen for this.
io.popen (prog [, mode])
Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is "r", the default) or to write data to this program (if mode is "w").
This function is system dependent and is not available on all platforms.
Also see How to execute an external command?.
io.popen calls a command but returns a file object so you can read the output of the command, if the second argument is 'r', but you can also pass input to a command with a second argument of 'w'. Unfortunately, you don't get a io.popen2, and you don't get the return code.

"attempt to call global 'tonumber' (a nil value)" in Lua, embedded (in VLC)

I use VLC media player 1.1.9 on Ubuntu 11.04. I'm trying to experiment with lua extensions for VLC; so I've added the file test.lua in ~/.local/share/vlc/lua/extensions/, which has only these two lines:
fps="25.000"
frame_duration=1/tonumber(fps)
When I run vlc with verbose output for debugging, I get (edited to split on multiple lines:):
$ vlc --verbose 2
...
[0xa213874] lua generic warning: Error loading script
~/.local/share/vlc/lua/extensions/test.lua:
.../.local/share/vlc/lua/extensions/test.lua:2:
attempt to call global 'tonumber' (a nil value)
...
Now, as far as I know, tonumber as function is part of Lua5.1 proper (Lua 5.1 Reference Manual: tonumber) - and on my system:
$ locate --regex 'lua.*so.*' | head -4
/usr/lib/libipelua.so.7.0.10
/usr/lib/liblua5.1.so
/usr/lib/liblua5.1.so.0
/usr/lib/liblua5.1.so.0.0.0
... apparently I do have Lua 5.1 installed.
So, why do I get an error on using tonumber here - and how can I use this (and other) standard functions in a VLC lua extension properly?
Documentation is sparse for VLC Lua extensions to say the least but I did find an example in the github vlc repository here: https://github.com/videolan/vlc/blob/master/share/lua/extensions/VLSub.lua
Judging from that example it appears you need to supply some basic event functions for your addon for VLC to call into when certain events happen. Some of the obvious callback handlers I've noticed:
descriptor, this should return a table that contains fields describing your addon.
activate, this seems to get called when you activate it from view menubar.
deactivate, called when you deactivate the addon from view menubar.
plus a couple of other functions like close and input_change which you can guess what they're for.
From my brief testing done on VLC 2.0.8 under Win7 it appears VLC loads the lua extension using an empty sandbox environment. This is likely the reason you're getting nil for tonumber and I'm betting none of the other standard lua functions are accessible either when you try to perform computation at this global scope.
However, if I move that code into one of the event handling functions then all those standard functions are accessible again. For example:
function descriptor()
return
{
title = "Test Ext";
version = "0.1";
author = "";
shortdesc = "Testing Lua Extension";
capabilities = {};
description = "VLC Hello Test Addon";
}
end
function activate()
print "test activating"
local fps = tonumber "25.000"
local frame_duration = 1 / fps
print(frame_duration)
return true
end
-- ...
That prints out what you would expect in the console debug log. Now the documentation (what little there is) doesn't mention any of this but what's probably happening here is VLC is injecting the standard lua functions and vlc api table into the sandboxed environment when any of these event handlers get called. But during the extension loading phase, it is done in an empty sandbox environment which explains why all those lua function calls end up being nil when you try to use it at the outter most scope.
I recommend cloning the VLC source tree from github and then performing a grep on the C source that's embedding lua to see what VLC is really doing behind the scenes. Most of the relevant code will likely be here: https://github.com/videolan/vlc/tree/master/modules/lua
Probably some extension script installed in your system overwrites the function and the Lua interpreter instance is shared between all extension scripts, so you end up not being able to call the function if that script is called before yours.
As a quick workaround, Lua being dynamically typed, you can still do things like:
1 / "25.000"
and the string will be coerced to a number.
Alternatively, you can define a tonumber equivalent like:
string_to_num = function(s) return s + 0 end
This again relies on dynamic typing.

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.

Calling back to a main file from a dofile in 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.

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