I'm having some trouble understanding how to use coroutines properly with luabind. There's a templated function:
template<class Ret>
Ret resume_function(object const& obj, ...)
Where (Ret) is supposed to contain the values passed to yield by Lua.
My current points of confusion are:
What happens if the function returns rather than calling yield? Does resume_function return the function's return value?
How are you supposed to use this function if you don't know ahead of time which (or how many) parameters will be passed to yield? For example, if there are multiple possible yielding functions the function may call.
What is the type of Ret if multiple values are passed to yield?
Am I just entirely mistaken as to how all this works? I envision something like this. On the Lua side:
local img = loadImage("foo.png")
loadImage would be a C++ function which requests the image to be loaded in a different thread and then calls lua_yield, and some time later luabind::resume_function gets called with img as a parameter.
Should I pass "foo.png" to yield as a parameter? To a different function before I call yield, and then never pass any values to yield? What's the right way to structure this? I'm obviously misunderstanding something here.
Where (Ret) is supposed to contain the values passed to yield by Lua.
Luabind only supports single return values, so it only will return the first value passed to coroutine.yield.
What happens if the function returns rather than calling yield? Does resume_function return the function's return value?
Yes, you get its return value.
How are you supposed to use this function if you don't know ahead of time which (or how many) parameters will be passed to yield? For example, if there are multiple possible yielding functions the function may call.
That's up to you; they're your functions. You have to develop conventions about what the yielding function(s) receive as parameters, and what the function resuming the coroutine provides.
What is the type of Ret if multiple values are passed to yield?
Whatever you want it to be. It's the template parameter. The number of parameters to a function has no bearing on the return values that the function provides.
Remember: Lua functions take any number of parameters and can return anything. All Luabind can do is pass along the parameters you give it and convert the return value from Lua functions into what you expect that return value to be. Luabind will do type-checking on the return value of course. But it is your responsibility to make sure that the functions yielding/returning will return something that is convertable to the type the user provides for Ret.
loadImage would be a C++ function which requests the image to be loaded in a different thread and then calls lua_yield, and some time later luabind::resume_function gets called with img as a parameter.
If you're using Luabind, never call lua_yield directly. The proper way to yield in Luabind is to add an attribute to a function you register that will yield whenever you return from the function. The syntax is as follows:
module(L)
[
def("do_thing_that_takes_time", &do_thing_that_takes_time, yield)
];
That is, a C++ function that yields must always yield. This is a limitation of Luabind, as with regular Lua, you can choose whether to yield or not as you see fit.
Also, don't forget that Lua coroutines are not the same thing as actual threads. They are not preemptive; they will only execute when you explicitly tell them to with coroutine.resume or an equivalent resume call.
Also, you should never run the same Lua instance from multiple C/C++ threads; Lua is not thread-safe within the same instance (which more or less means the same lua_State object).
What you seem to want to do is have Lua call some function in C++ that itself spawns a thread to do some process, then have the Lua code wait until that thread is complete and then receives its answer.
To do that, you need to give to the Lua script an object that represents the C++ thread. So your loadImage function should not be using coroutine logic; it should return an object that represents the C++ thread. The Lua script can ask the object if it has completed, and if it has, it can query data from it.
The place where coroutines can come into play here is if you don't want the Lua script to wait until this is finished. That is, you're calling the Lua script every so often, but if the C++ thread isn't done, then it should just return. In which case, you can do something like this:
function loadImageAsCoroutine(imageFilename)
local cppThread = cpp.loadImage(imageFilename);
local function threadFunc(cppThread)
if(cppThread:isFinished()) then
local data = cppThread:GetImage();
return data;
else
coroutine.yield();
end
end
local thread = coroutine.create(threadFunc);
local errors, data = assert(coroutine.resume(thread, cppThread));
if(coroutine.status(thread) == "dead") then
return data;
else
return thread;
end
end
This function returns a coroutine or the image data itself. The caller of this function should check the type; if the type is "thread", then the C++ thread hasn't finished yet. Otherwise, it is the image data.
The caller of this function can pump the coroutine however much they want with some equivalent of coroutine.resume (whether it's luabind::resume_function or whatever). Each time, check the return value. It will be nil if the C++ thread hasn't finished, and not nil otherwise.
Related
I have a piece of lua code that is called from a C program that passes it a table.
The table contains a table which has a field that LUA reports is of type "function".
I want to invoke that function and get its return value, but the following just causes a crash (????stack corruption????):
function myFunc (tableIn)
local interface = tableIn["interface"] -- type(interface) is table
local targetFunc = interface["targetFunc"] -- type(targetFunc) is function
local value = targetFunc()
...
end
I'm therefore assuming that I need to pass one or more parameters to targetFunc(...) but I have no idea what targetFunc() is expecting and I don't have access to the documentation or code for targetFunc - which I'm also guessing is written in C.
I've seen the thread lua - get the list of parameter names of a function, from outside the function and run the code as suggested - but that just seems to return "*temporary".
The question: is there some "standard" way of calling a C routine from LUA - or is there any other programmatic way (even a one-off) of finding out how many and what type of parameters targetFunc(...) needs.
Even an answer of "no - you need to see the code / doc for targetFunc(...)" would help!
Thanks in advance...
I have a third party API that has an event listener adding function which takes as parameter a callback function to be triggered when the event occurs. I would like to pass argument to that callback function. I'm looking for Lua's equivalent of JavaScript's bind.
The Lua code:
EventListenerAddingFunction(myCallbackFunction); // I want to add a param to the callback here
How I would do it in JS:
EventListenerAddingFunction(myCallbackFunction.bind({}, myParameter));
Can this be done in Lua?
No Lua doesn't have this feature, so closest I can think of would be making a closure-wrapper:
EventListenerAddingFunction(function(...) myCallbackFunction({}, myParameter, ...) end)
This passes your parameter everytime the callback is called, all other callback parameters will be passed next. If you don't know your parameters use ... (I don't know them so I used varargs), it's better if you pass exact amount of parameters.
I'm fairly new to Dart and been trying to understand why a calling function needs to return a future? I get why the called function needs to return a future, but not the calling function itself. This doesn't seem to make sense and confuses the logic. For example, say I wanted:
List<String> someFunct() async {
final _res = await someFuture();
return _res.toList();
}
I can't do this without wrapping the calling function's return in a Future that then propagates this async model up the calling tree. The calling function is not a future, so it shouldn't need to return a future.
An asynchronous function is one which doesn't complete its work immediately when it's called. That's why it returns a Future, which is an object which will eventually make the result available.
All functions must return something when they are called. Dart does not support blocking, where a function simply stops in the middle and lets other code run until it's ready to continue, because that requires having separate stacks, and it can't be efficiently compiled to JavaScript. So an asynchronous function must return something immediately, and that something is a future.
Returning the future allows the calling function to wait until the result is available. It has to, if it needs to use the result.
In your example, someFunct wants to return a list which isn't available until later. It cannot simply return a list immediately, because it doesn't have the list yet. So, it must return a Future<List<String>>.
The one case where you don't need to return a future from an otherwise asynchronous function is when the calling function doesn't care about the result, or it gets the result in some other way, say by it being added to a collection when it's ready. Then you can just return void, and not bother with a future.
In the vast majority of cases, your asynchronous functions must return a future, because they want to return something, and that's all they have available before the real result is ready.
I want to use a Lua API which has specific callback functions when events occur, e.g. when an TCP package arrives. At first the function have to be registered but by the functions name as a string, see the sample code below
function __init__()
local dstport = 4681
local dstIP = "192.168.1.42"
-- register the callback function
register_tcp_handler('tcp_package_handler', dstIP, dstPort)
end
-- callback function
function tcp_package_handler(srcIP, srcPort, dstIP, dstPort, payload)
-- check the payload, or reset watchdog
end
It would be nice to have other variables in callback function provided by the callee, e.g. watchdog-timer or other objects.
The most simple way I could think of is to make the extravariables global, but it is the least elegant way I reckon. Closures would be helpful if I could pass the function directly, but i can not. I have to use the functions name as a string.
Considering this mechanics, is there a more elegant way to privide variables to the callback function without making them global?
EDIT: Using closures like this
function closure_tcp_package_handler(srcIP, srcPort, dstIP, dstPort, payload, packagecounter, timerobject)
function tcp_package_handler(srcIP, srcPort, dstIP, dstPort, payload)
-- do some stuff, change packagecounter, timerobject
end
return 'tcp_package_handler'
end
and use this function twice to register, e.g. with packagecounter1, timerobject1 and packagecounter2, timerobject2, only the last pair of parameters will be changed.
You're dealing with a callback infrastructure. In which case, your code is not the one invoking the handler. As such, there's no way to hide those parameters; if you can change them, so can someone else with access to the module providing the handler.
That doesn't mean that they have to be global, of course. You could make them members of a table. You could even provide setter functions to set the parameters, if you want to make sure that they only get certain parameters.
The simple form of this is as follows:
local handler_params = {}
function tcp_package_handler(srcIP, srcPort, dstIP, dstPort)
-- check `handler_params.payload`
end
--Make `handler_params` available for outside modification
How you do that last part is entirely up to you. You could have made it a global, but if this is in a module somewhere, it'd be better to make it a member of that module's table. And again, if you want to have some control over who gets to poke at it and how, you can use setter functions:
function tcp_handler_set_payload(payload)
handler_params.payload = payload
end
I have some code that wants to do grab some extra return values from a function and pass them forward latter on:
local ok, ... = coroutine.resume(co)
do_stuff(ok)
return ...
However, this won't run since the ... on the variable assignment is a syntax error.
I could work around this limitation by using the old "functions arguments and variables are equivalent" trick and an immediately-invoked function
return (function(ok, ...)
do_stuff(ok)
return ...
)(coroutine.resume(co))
but I imagine doing so wouldn't be very idiomatic or efficient. Are there more reasonable ways to solve this problem of handling the remaining values returned from the resume call?
EDIT: By the way, this needs to work with nil values in the extra arguments
EDIT2: Looks like using the immediately invoked function was the best way all along.
IMHO, the best way is passing vararg as parameter to helper function as you have done in your question.
The alternative way is "pack-unpack":
-- Lua 5.2 only
local t = table.pack(coroutine.resume(co))
do_stuff(t[1])
return table.unpack(t, 2, t.n)
The idiomatic way to do this with an unknown number of return values is to wrap the function call in a table constructor:
local t = { coroutine.resume(co) }
do_stuff(table.remove(t, 1))
return unpack(t) -- table.unpack(t) in lua 5.2
While this also involves creating a temporary object, it should be a lot quicker than using a closure, and it's certainly a lot neater.