luaL_loadbufferx returns syntaxerrors - lua

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.

Related

Can Erlang source code be embedded in Elixir code? If so, how?

Elixir source may be injected using Code.eval_string/3. I don't see mention of running raw Erlang code in the docs:
https://hexdocs.pm/elixir/Code.html#eval_string/3
I am coming from a Scala world in which Java objects are callable using Scala syntax, and Scala is compiled into Java and visible by intercepting the compiler output (directly generated with scalac).
I get the sense that Elixir does not provide such interoperating features, nor allow injection of custom Erlang into the runtime. Is this the case?
You can use the erlang standard library modules from Elixir, as described here or here.
For example:
def random_integer(upper) do
:rand.uniform(upper) # rand is an erlang library
end
You can also add erlang packages to your mix.exs dependencies and use them in your project, as long as these packages are published on hex or on github.
You can also use erlang and elixir code together in a project as described here.
So yeah, it's perfectly possible to call erlang code from elixir.
Vice-versa is also possible, see here for more information:
Elixir compiles into BEAM byte code (via Erlang Abstract Format). This
means that Elixir code can be called from Erlang and vice versa,
without the need to write any bindings.
Expanding what #zwippie have written:
All remote function calls (by that I mean calling function with explicitly set module/alias) are in form of:
<atom with module name>.<function name>(<arguments>)
# Technically it is the same as:
# apply(module, function_name_as_atom, [arguments])
And all "upper case module names" in Elixir are just atoms:
is_atom(Foo) == true
Foo == :"Elixir.Foo" # => true
So from Elixir viewpoint there is no difference between calling Erlang functions and Elixir functions. It is just different atom passed as the receiving module.
So you can easily call Erlang modules from Elixir. That mean that without much of the hassle you should be able to compile Erlang AST from within Elixir as well:
"rand:uniform(100)"
|> :merl.quote()
|> :erl_eval.expr(#{})
No need for any mental translation.
Additionally you can without any problems mix Erlang and Elixir code in single Mix project. With tree structure like:
.
|`- mix.exs
|`- src
| `- example.erl
`- lib
`- example.ex
Where example.erl is:
-module(example).
-export([hello/0]).
hello() -> <<"World">>.
And example.ex:
defmodule Example do
def print_hello, do: IO.puts(:example.hello())
end
You can compile project and run it with
mix run -e "Example.print_hello()"
And see that Erlang module was successfully compiled and executed from within Elixir code in the same project without problems.
One more thing to watch for when calling erlang code from elixir. erlang uses charlists for strings. When you call a erlang function that takes a string, convert the string to a charlist and convert returned string to a string.
Examples:
iex(17)> :string.to_upper "test"
** (FunctionClauseError) no function clause matching in :string.to_upper/1
The following arguments were given to :string.to_upper/1:
# 1
"test"
(stdlib 3.15.1) string.erl:2231: :string.to_upper/1
iex(17)> "test" |> String.to_charlist() |> :string.to_upper
'TEST'
iex(18)> "test" |> String.to_charlist() |> :string.to_upper |> to_string
"TEST"
iex(19)>

"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.

require function fails at lua_load with SYNTAX ERR

I am new to Lua. I have ported Lua 5.2 to another platform. I am able to run Lua scripts.
But have a problem with loading modules.
I have a sample.lua script below. In this script I am trying to call a function available in another Lua script using the require function. The require function fails at lua_load() with LUA_ERRSYNTAX. Not sure if this is problem with Lua 5.2 version.
sample.lua
require"module"
welcome()
module.lua
function welcome()
print(" Hello in module")
end
The require function in sample.lua file locates the module.lua file but fails at lua_load().
Can anyone help me with this issue ?
Could You be more specific about those different OS'es? Firstly, You should compile Lua for exactly the same OS and device Your are running *.lua scripts on. Secondly, You should check module.lua for some weird typos and invisible symbols. String.char(195) doesn't seem very visible. Also, could You check the enconding of that/those two Lua scripts?

Function from other module not detecting

I two modules in same src folder. mod1 declares function I wish to use in module mod2:
-module(mod1).
-export([myfunc/1]).
myfunc(A) -> {ok}.
In other module I not import mod1:
-module(mod2).
If I do "mod1:" in mod2 it recognizes "myfunc", problem is at run-time when I call mod1:myfunc(A) I get "undefined function mod1:myfunc/1"
I not understand why I get error if intellisense detect my mod1 function in mod2?
From the shell, you could try doing mod1:module_info(exports) to see the list of all the exported functions, though if your module is written as it is above, it should be generating a syntax error.
If, however, I'm wrong, and you actually do have it written properly in your module, (ie, it's just a typo here), try doing the following at the erlang shell:
c(mod1).
c(mod2).
And see if that works for you. This will compile and load the modules for you. If you don't have the module compiled (ie, it's just a .erl file in the directory), that's insufficient.
EDIT
Also, make sure that the beam files are being loaded properly when erlang launches. This is typically done by launching erl with erl -pa /path/to/beams

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.

Resources