How to run multiple instances of a lua script from C - lua

I have the following lua script :
mydata={}
function update(val)
mydata["x"] = val
if (val == 10)
-- Call C-Api(1)
else
--Register callback with C when free or some event happens
register_callback(callme)
end
function callme()
end
Basically I would like to have two instances of this script running in my C program/process with out having to create a new LUA state per script. And I want to call the function update() with val = 10 from the one instance and call the function update() with val = 20 from another instance. From the second instance it registers a callback function and just waits to be called.
Basically the script file is kind of a RULE that i am trying to achieve.
Several events on the system can trigger this rule or script file. I would like to process this rule as per the event that triggered it. There could be multiple events triggering this script to run at the same time. So I need to have multiple instances of this script running differentiated by the kind of event that triggered it.
To Summarize, I want each caller to have separate individual instance of mydata
I would like to achieve something like this. I read some where that we should be able to run multiple instances of a lua script with out having to create a new lua instance by loading a new environment before loading the script
But I am not able to find the exact details.
Could some body help ?

While I'm still not sure what exactly you are trying to achieve, but if you want to have two instances of the same function that keep the data they use private, you just need to create a closure and return an anonymous function that your C code will use.
Something like this should work:
function createenv(callme)
local mydata={}
return function (val) -- return anonymous function
mydata["x"] = val
if (val == 10)
-- Call C-Api(1)
else
--Register callback with C when free or some event happens
register_callback(callme)
end
end
end
Now in one part of your (C or Lua) code you can do:
local update = createenv(function() --[[do whatever]] end)
update(10)
And then in another part you can do:
local update = createenv(function() --[[do something else]] end)
update(20)
And they should have nothing in common between each other. Note that they still shared the same Lua state, but their instances of mydata will be independent of each other.

Related

Lua (require) invoke an not intended print of required file name

When require is called in testt.lua which is one of two files the return is movee and movee.lua.
movee are for the most part a class to be required, but should be able to accept to be called direct with parameter.
movee.lua
local lib = {} --this is class array
function lib.moveAround( ... )
for i,direction in ipairs(arg) do
print(direction)
end
end
function lib.hello()
print("Hello water jump")
end
lib.moveAround(...)
return lib
testt.la
local move = require("movee")
Expected result is not to call lib.moveAround or print of file name when require is called.
Your expectations are incorrect. Lua, and most scripting languages for that matter, does not recognize much of a distinction between including a module and executing the Lua file which provides that module. Every function statement is a statement whose execution creates a function object. Until those statements are executed, those functions don't exist. Same goes for your local lib = {}. And so on.
Now, if you want to make a distinction between when a user tries to require your script as a module and when a user tries to execute your script on the command line (or via just loadfile or similar), then I would suggest doing the following.
Check the number of arguments the script was given. If no arguments were given, then your script was probably required, so don't do the stuff you don't want to do when the user requires your script:
local nargs = select("#", ...)
if(nargs > 0) then
lib.moveAround(...)
end
Solved by replacing
lib.moveAround(...)
with
local argument = {...}
if argument[1] ~= "movee" and argument[2] ~= "movee" then
lib.moveAround(...)
end
require("movee")
will execute the code within movee.lua
lib.moveAround(...)
is part of that code. Hence if you require "movee" you call lib.moveAround
If the expected result is not to call it, remove that line from your code or don't require that file.

How do I unit test Lua modules without OO?

In Lua I can write a simple module like so
local database = require 'database'
local M = {}
function M:GetData()
return database:GetData()
end
return M
Which when required, will load once, and all future versions will load the same copy.
If I wanted to take an object-oriented approach I could do something like:
local M = {}
M.__index = M
function M:GetData()
return self.database:GetData()
end
return function(database)
local newM = setmetatable({}, M)
newM.database = database
return newM
end
Where M is only loaded once, and each copy of newM just holds its own data and uses the methods of the original M.
When it comes to testing, with the OO approach I can just pass in a fake version of 'database' and check it gets called, but with the first approach I can't.
So my question is how can I make the first approach support DI/testing without making it class-like?
My thought was to wrap it in a closure something like this:
local mClosure = function(database)
local M = {}
function M:GetData()
return database:GetData()
end
return M
end
return mClosure
but then every time it is called it will create a new copy of M, so it will lose the benefits of both of the previous approaches.
That's clearly a use case for the Lua debug library. With that you can just modify the upvalues of your function and inject dependancies. Also consider that you can use require for this; just require your database module once, create small table that collects data and then redirects to the original module and put it in package.loaded so the next time you require it, the require call returns the modified version of the module. The OO approach is how you would do this kind of thing in a language like Ruby, but in Lua we have way nicer ways of tapping into a module or function without it being specifically designed for that purpose.
local real_db = require 'db'
local fake_db = setmetatable({}, {__index=db})
function fake_db.exec(query) print('running query: '..query) end -- dummy function
function fake_db.something(...) print('doing something'); real_db.something(...) end
package.loaded.db = fake_db
require 'my_tests' -- this in turn requires 'db', but gets the fake one
package.loaded.db = real_db
-- After this point, `require 'db'` will return the original module

Intercept Global Function

Is it possible to intercept a global function call, and run another function when the global is called.
local test = global()
function test()
print("Hello World")
end
I've tried this but it doesn't seem to work.
Edit
My original question was phrased poorly I ended up coming up with this solution. The functions I'm trying to change are inside of a table so I just make a copy of the table, overwrite the function and then copy the backup table over the original to restore the function.
copy = {}
i,v = next(globaltable, nil)
while i do
copy[i] = v
i,v = next(globaltable,i)
end
function globaltable:function()
do some stuff
globaltable = copy
end
If you want to actually call test when calling global(), assign test to global:
local old_global = global
global = test
This makes global to refer to the function object of test.

LuaJ loading two functions with the same name from two different LuaScripts

I have two Lua Scripts containing functions with the same name:
luaScriptA:
function init()
print( 'This function was run from Script A' )
end
luaScriptB:
function init()
print( 'This function was run from Script B' )
end
I would like to load both these functions using LuaJ into the globals environnment, for one script I usually do it as follows:
LuaValue chunk = globals.load(new FileInputStream(luaScriptA), scriptName, "t",
globals);
chunk.call();
This will load the function init() into globals and I can execute this function from java with:
globals.get("init").call();
The problem comes in when I load a second script, this will overwrite all functions with the same name previously declared. Is there any way I can prevent this and easily distinguish between the two functions? For example something like:
globals.get("luaScriptA").get("init").call(); //Access the init function of script A
globals.get("luaScriptB").get("init").call(); //Access the init function of script B
Please note that the script contains other functions as well and my goal is to run individual functions within the script, not the complete script at once.Working on the JME platform.
Put your functions in a table
luaScriptA:
A = {} -- "module"
function A.init()
print( 'This function was run from Script A' )
end
luaScriptB:
B = {} -- "module"
function B.init()
print( 'This function was run from Script B' )
end
Then you would do
globals.get("A").get("init").call();
globals.get("B").get("init").call();
The code below loads scripts in their own environment, which inherits from the global one for reading but not for writing. In other words, you can call print but each defines its own init. You'll probably have to do something to use it in LuaJ, but I don't know what.
local function myload(f)
local t=setmetatable({},{__index=_G})
assert(loadfile(f,nil,t))()
return t
end
local A=myload("luaScriptA") A.init()
local B=myload("luaScriptA") B.init()

Post-hook a function, post-process and pass through all returns

I have a post-hook function that receives some data for itself, reference to another function and arguments for that arbitrary function in .... This function does some post-processing, after referenced function returns. For simplicity let's just note time:
function passthrough(tag, func, ...)
metric1[tag] = os.time()
func(...)
metric2[tag] = os.time()
end
Since I need to postprocess, I can't immediately return func(...) and I don't know in advance how many returns there will be. How can I passthrough those returns after I'm done with post-processing?
So far I can think only of packing call in local results = { func(...) } and then using return unpack(results) or making a postprocessor factory that'd generate postprocessing closure with all necessary data as upvalues:
local function generate_postprocessor(tag)
return function(...)
metric2[tag] = os.time()
return ...
end
end
function passthrough2(tag, func, ...)
metric1[tag] = os.time()
return generate_postprocessor(tag)(func(...))
end
However, both those approaches would introduce some overhead that is undesirable, considering high amount of iterations and real-time nature of application. Is there anything simpler?
You don't need the closure. func is called before calling your closure generator anyway. You just need a function that passes its arguments straight through to its return values to give you a hook point for your second tag:
function passthrough_return(tag, ...)
metric2[tag] = os.time()
return ...
end
function passthrough(tag, func, ...)
metric1[tag] = os.time()
return passthrough_return(tag, func(...))
end
You're still getting the overhead of an extra function call, but that's better than creating a closure or a table and far less than the overhead of your pre/post processing.

Resources