Lua package containing subpackages - lua

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

Related

How do I load data from another lua file?

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

lua -> how to modify these arguments to be const, or what should I do?

all!
I came here because I have one problem bugging me for quite some time now. I am using love2d engine as a 'graphical' addition to lua scripting, but this problem is of lua type (I believe, at least).
I have a function:
createNew_keepOld = function (oldImgData, oldImgDraw)
local newImgData = oldImgData --I am assigning old value to another variable
local newImgDraw = oldImgDraw --I am doing the same thing as with data
for x = 0, newImgData:getWidth()-1 do
for y = 0, newImgData:getHeight()-1 do
local r, g, b, a = newImgData:getPixel(x, y)
r = 2*r
g = 2*g
b = 0.5*b
a = 2*a
newImgData:setPixel(x, y, r, g, b, a)
end
end
newImgDraw:replacePixels(newImgData)
return newImgData, newImgDraw
end
When this code finishes, I get the change I need, but not WHERE I want it. I just want to produce two new variables which will store data and image objects. But, in process, original image gets changed.
Is there any way to declare:
name = function (const param, const param)
return some_things
end
So that I get output I need without changing the original stuff? Or is there some problem with my code that I cannot see?
Thanks!
Actually the nature of this problem is both in Love2D and Lua. Anyway.
Quote from Lua Reference Manual 5.3:
Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.
Most types from Love2D are of userdata Lua type, so when passing them to your function you are actually passing reference to them, hence you modify the "old" versions in the very end. Those types usually have functions made for copying them.
ImageData does have one and Image does not, but you can do the following:
createNew_keepOld = function (oldImgData, oldImgDraw)
local newImgData = oldImgData:clone()
for x = 0, newImgData:getWidth()-1 do
for y = 0, newImgData:getHeight()-1 do
local r, g, b, a = newImgData:getPixel(x, y)
r = 2*r
g = 2*g
b = 0.5*b
a = 2*a
newImgData:setPixel(x, y, r, g, b, a)
end
end
local newImgDraw = love.graphics.newImage(newImgData, oldImgDraw:getFlags())
return newImgData, newImgDraw
end
Note that I created entirely new Image based on copied ImageData and image flags from the old one.
In Lua when you make a variable equal to a table value you are not copying or duplicating that information. The new variable simply points to the same values as the other variable.
Example:
tbl1 = {}
tbl2 = tbl1
tbl2[1] = 1
print(tbl1[1])
In order to create a newImgDatabased on oldImgData you need to preform a deep copy:
function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
Resource for table copying: Lua-Users Wiki: Copy Table
This Solution only works a table type, it will not work for userdata

Returning a string table array from C to LuaJIT via FFI

I would like to have a C function return a string table array (e.g. {"a", "b", "c"}) to a Lua script via LuaJIT.
Which is the best way to do it?
I thought of returning a single concatenated string with some separator (e.g. "a|b|c") then splitting it in Lua, but I was wondering if there is a better way.
EDIT: I'm using LuaJIT FFI to call C functions.
I think the easiest way to accomplish this would be to have the C code return a struct containing an array of strings and a length to Lua and write a little Lua to reify it to your desired data structure.
In C:
typedef struct {
char *strings[];
size_t len;
} string_array;
string_array my_func(...) {
/* do what you are going to do here */
size_t nstrs = n; /* however many strings you are returning */
char** str_array = malloc(sizeof(char*)*nstrs);
/* put all your strings into the array here */
return {str_array, nstrs};
}
In Lua:
-- load my_func and string_array declarations
local str_array_C = C.ffi.my_func(...)
local str_array_lua = {}
for i = 0, str_array_C.len-1 do
str_array_lua[i+1] = ffi.string(str_array_C.strings[i])
end
-- str_array_lua now holds your list of strings

Getting a “pointer” to a Lua function stored in C

In the Lua C API I can store a number or a string from the stack with lua_tostring().
How can a “reference” (if that is the correct term) to a Lua function be passed to C through the Lua API? So it can be called later from C, with lua_call(), without having to reference it by its name.
(It really needs to be like that, the C program will call the function somewhere in the future and the program doesn't know anything about the function because the functions to be passed are defined in the Lua program)
In C you can't refer to Lua functions directly but you can represent numbers and strings. So, for a function to "be called later", you can store this function in some table and refer to it by a numeric or string key of the table.
Here's a simpleminded mechanism to start with:
On the Lua side:
funcs = {}
local function register_hanlder(key, fn)
funcs[key] = fn
end
register_handler("on_mouse_click", function()
print "You clicked me!"
end)
On the C side:
/* code not tested */
lua_getglobal(L, "funcs");
lua_getfield(L, -1, "on_mouse_click");
if (!lua_isnil(L, -1)) {
lua_call(L, 0, 0);
else {
// nothing registered
}
Instead of registering the functions in a global table you can register them in the registry table (see luaL_ref). You'll get some integer (that's the key in the registry table where the function value is) that you can pass around in you C code.
Note that if you don't need to store a Lua function "for use later" you don't need any of this: if your C function has some Lua function passed to it via argument you can call it outright.
== Edit:
As I mentioned, instead of using a global variable (the funcs above) you can store the reference to the function in the "registry". Conceptually there's no difference between this method and the previous one.
Let's re-use the previous example: you want the Lua programmer to be able to register a function that would be fired whenever a mouse is clicked in your application.
The Lua side would look like this:
register_mouse_click_handler(function()
print "the mouse was clicked!"
end)
On the C side you define register_mouse_click_handler:
static int the_mouse_click_handler = 0;
static int register_mouse_click_handler(lua_State* L) {
the_mouse_click_handler = luaL_ref(L, LUA_REGISTRYINDEX);
return 0;
}
(...and expose it to Lua.)
Then, in your application, when the mouse is clicked and you want to call the Lua function, you do:
...
if (the_mouse_click_handler != 0) {
lua_rawgeti(L, LUA_REGISTRYINDEX, the_mouse_click_handler);
lua_call(L, 0, 0);
} else {
// No mouse handler was registered.
}
...
(I may have typos in the code.)

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