How do I load data from another lua file? - lua

I have a main lua file app.lua , and in that app I have a button to "load data" in.
NOTE: LUA 5.1 not 5.2
The data file is a lua file as well with tables in it.
data1 = {
{a,b,c},
{1,2,3}
}
data2 = {
{d,e,f}
}
The goal was to make those tables available to the app anytime I choose to load the file.
I tried the example from the lua site
function dofile (filename)
local f = assert(loadfile(filename))
return f()
end
but f() is just printing a massive string. I can't seem to access f.data1[1] for example.

The file you're loading is not a data table. That's a piece of code, anonymous function that is executable. You run that code in return f() statement.
But see what that code does - it doesn't return anything. Instead it assigns two global variables, data1 and data2. You can access those as data1[1] for example.
You could return the data in the file being loaded, that way it wouldn't pollute the global environment, and probably will look like you imagined it to be:
return {
data1 = { {a,b,c}, {1,2,3} },
data2 = { d,e,f}
}
And in other file:
local f = assert(loadfile(filename))
my_data = f()
print(my_data.data1[1][1])

Related

Parse Arguments to Lua File

I have File: data.lua
#! /usr/bin/env lua
local a = {
b = {
c = {
version = "z.y"
},
d = {
version = "z.w"
},
getcversion = function ( self )
print( self.c.version )
end
}
}
Now I need to 'getcversion()' Function..
a.b:getcversion()
The problem is, I need to call it from the outside:
data.lua "a.b:getcversion()"
I tried everything that I could, but I couldn't solve this..
Does any one knows how I could call 'getcversion()' ?
Thanks in Advance,
Regards
You'll need to add something like the following to your script:
load(arg[1], "<string>", "t", {a = a})()
load will load the content of the passed parameter (arg[1]) and will return the function that will execute that code in a specific environment (provided as {a = a} table), as you need to pass the values of local variables to your code (Lua 5.2+).
Keep in mind that this will allow the caller to pass arbitrary Lua code to your script, which may be a security issue.
The error handling is left as the exercise for the reader.
Add return a to the end of data.lua to turn it into a module, and then:
$ lua -e 'a = require("data"); print(a.b:getcversion())'
z.y

Create a simple Lua .txt Database with write() and read()

im trying to create a simple 2 functions text-file "database" with LUA. All i need is 2 Functions.
my db should look like that:
varName;varValue
JohnAge;18
JohnCity;Munich
LarissaAge;21
LarissaCity;Berlin
In fact im not stuck to any format! I just don't have a way to save data longterm in my lua enviroment and i need to find a workaround. So if you already have a
similiar solution at hand, please feel free to throw it at me. Thank you very much
Function WriteToDB(varName, varValue)
If database.text contains a line that starts with varName
replace whatever comes after seperator ";" with varValue (but dont go into the next line)
Function ReadFromDB(varName)
If database.text contains a line that starts with varName
take whatever comes after the seperator ";" and return that (but dont go into the next line)
elseif not found print("error")
Save the data as Lua code that builds a table:
return {
JohnAge = 18,
JohnCity = "Munich",
LarissaAge = 21,
LarissaCity = "Berlin",
}
Or better yet
return {
["John"] = {Age = 18, City = "Munich"},
["Larissa"] = {Age = 21, City = "Berlin"},
}
Load the data with
db = dofile"db.lua"
Access the data with
print(db["Larissa"].Age)
or
print(db[name].Age)

Convert a value string in metatable to table for lookup

I have an enormous table of functions named engine_api with inline documentation. Because it's becoming so large I'd like to make it more modular.
The api is set up like this:
-- Engine API module
local engine_api = {
engine = {
-- engine functions...
version = ...
},
image = {
-- image functions...
jpeg = {
-- jpeg specific bits
},
},
project = {
-- project functions
}
}
return engine_api
As you can see, it's more than 2 levels deep.
The whole thing is returned as a single table so other parts of the system can call into this api like this:
local api = require "engine_api"
print("Engine version:", engine_api.engine.version());
I still need it to work this way. But what I'd like to do is separate various parts of the API into different files. I thought I might be able to do this using metamethods. But when the metamethod is looked up, the value is actually a string so this naive approach will not work.
local engine = {
-- engine functions...
version = function()
print("engine.version")
end
}
local image = {
-- image functions
get = function()
print("image.get")
end
}
local project = {
-- project functions
load = function()
print("project.load()")
end
}
-- Engine API module
local engine_api = {
}
local engine_api_mt = {
__index = function(tbl, k)
print("k=", k)
return k
end
}
setmetatable(engine_api, engine_api_mt)
Instead I seem to have to do bunch of if then else statements to compare the table name with the string and then return the table and not the string. Is there a way of performing the conversion automatically?
You can make engine_api a single file and require files inside that table, like so:
engine_api.lua:
local engine_api = {
engine = require("engine"),
image = require("image"),
project = require("project"),
}
return engine_api
engine.lua:
local engine = {
version = function()
print("my version")
end
}
return engine
And so on, that way you can call engine_api.engine.version() with no problems at all. I think the metatable is just over the top, unless you are doing something more specific?

Lua package containing subpackages

I have written a number of modules for Lua in C. Each of these contains a Lua userdata type and I load and use them like this:
A = require("A")
B = require("B")
a = A.new(3,{1,2,3})
b1 = B.new(1)
b2 = B.new(2) * b1
Now I would like to put both userdata types in a single shared library AandB that can be used like this
AB = require("AandB")
AB.A.new(3,{1,2,3})
What is a good way to achieve this? Right now my luaopen_* functions look like this
int luaopen_A(lua_State *L) {
luaL_newmetatable(L, A_MT);
luaL_setfuncs(L, A_methods, 0);
luaL_newlib(L, A_functions);
return 1;
};
And is it possible then to still load only part, e.g. like this: A = require("AandB.A")?
require("AandB.A") works if you define luaopen_AandB_A in your C library, which must be called AandB.so.
In general, require replaces dots with underscores when trying C libraries.
One thing you can do is to write a lua script module that pulls in both A and B. You can then require that script from your using code:
-- AandB.lua
return { A = require 'A', B = require 'B' }
If you only want to load part of your module, you can just do:
A = require "AandB".A

Read lua interface

In lua, is there any way to read an interface file to extract name/methods/args?
I have an .idl file like this:
interface
{
name = myInterface,
methods = {
testing = {
resulttype = "double",
args = {{direction = "in",
type = "double"},
}
}
}
This is equal to the code bellow (easier to read):
interface myInterface {
double testing (in double a);
};
I can read file, load as string and parse with gmatch for example to extract information, but is there any easy mode to parse this info?
At the end i want something (a table for example) with the interface name, their methods, result types and args. Just to know the interface that i`m working.
Lua has several facilities to interpret chunks of code. Namely, dofile, loadfile and loadstring. Luckily, your input file is almost valid Lua code (assuming those braces were matched). The only thing that is problematic is interface {.
All of the above functions effectively create a function object with a file's or a string's contents as their code. dofile immediately executes that function, while the others return a function, which you can invoke whenever you like. Therefore, if you're free to change the files, replace interface in the first line with return. Then you can do:
local interface = dofile("input.idl")
And interface will be a nice table, just as you have specified it in the file. If you cannot change those files to your liking, you will have to load the file into the string, perform some string manipulation (specifically, replace the first interface with return) and then use loadstring instead:
io.input("input.idl")
local input = io.read("*all")
input = string.gsub(input, "^interface", "return") -- ^ marks beginning of string
local f = loadstring(input)
local interface = f()
In both cases this is what you will get:
> require"pl.pretty".dump(interface)
{
name = "myInterface",
methods = {
testing = {
args = {
{
type = "double",
direction = "in"
}
},
resulttype = "double"
}
}
}
> print(interface.methods.testing.args[1].type)
double
EDIT:
I just realised, in your example input myInterface is not enclosed in " and therefore not a proper string. Is that also a mistake in your input file or is that what your files actually look like? In the latter case, you would need to change that as well. Lua is not going to complain if it's a name it doesn't know, but you also won't get the field in that case.

Resources