Lua & C++ : running a dynamic snippet? - c++

I have a Lua thread running, and a Qt-powered text edit running in parallel. I want the user to be able to run any Lua code he has written in the text edit, but it doesn't work well. It works with simple instruction(s), like "print(5)" or "tmp = 5; print(tmp)" but it doesn't work with strings (print( "hello world") ) or numeric expressions like print(5+3).
And, worst of all, it doesn't work if I try to call a lua function defined before or a C registered function.
If I delete signals&slots etc, my code is roughly this :
const char* text = textEdit->toPlainText().toLatin1().data();
luaL_loadstring(_LuaState, text);
lua_pcall(_LuaState, 0, LUA_MULTRET, 0); ///These 2 lines used to be luaL_doString,
// but it didn't work
the Lua State is the same that the one where I registered C functions and loaded a lua file defining some others functions

Related

Maintaining lua/c++ variables through through multiple script calls

I'm pretty new to lua scripting, but want to incorporate scripting into my game engine. Currently I have lua linked up to c++ in a basic manner where I can call methods from c++ classes and vise-versa. Lua scripts are setup as components and you can essentially attach scripts to a game object. However, I'm having an issue where my variables are being reset each time a script is called. Here is a basic example of a script:
--lua script--
input = InputManager()
function initalize()
end
function update()
if(input:KeyDown(KEY_SPACE)) then
print("Random before: ", input.random)
input.random = input.random + 10
print("Random after: ", input.random)
end
end
Initialize is called when the script component is attached and update is called every frame. In this example, in my c++ InputManager class that I bind up to lua, I have a integer random that is initialized to 5. I'm using lunafive properties to control the getting and setting of variables.
When I hit space i expect the first iteration to print out:
Random before: 5
Random after: 15
And then the next iteration:
Random before: 15
Random after: 25
However, every iteration I get that first result of 5 and 15. I realize this is because I'm loading the script each update method so it is probably just creating a new instance of InputManager.
How do I go about creating an instance of an object (i.e InputManager) and maintain that same instance every time I call update.
That way I could do something like this:
input = nil
function initalize()
input = InputManager()
end
function update()
print(input.random)
end
and not have an undefined instance of input once update is called. Hopefully this all makes sense, if not I can clarify! Any help is much appreciated!

How to test asynchronuous code

I've written my own access layer to a game engine. There is a GameLoop which gets called every frame which lets me process my own code. I'm able to do specific things and to check if these things happened. In a very basic way it could look like this:
void cycle()
{
//set a specific value
Engine::setText("Hello World");
//read the value
std::string text = Engine::getText();
}
I want to test if my Engine-layer is working by writing automated tests. I have some experience in using the Boost Unittest Framework for simple comparison tests like this.
The problem is, that some things I want the engine to do are just processed after the call to cycle(). So calling Engine::getText() directly after Engine::setText(...) would return an empty string. If I would wait until the next call of cycle() the right value would be returned.
I now am wondering how I should write my tests if it is not possible to process them in the same cycle. Are there any best practices? Is it possible to use the "traditional testing" approach given by Boost Unittest Framework in such an environment? Are there perhaps other frameworks aimed at such a specialised case?
I'm using C++ for everything here, but I could imagine that there are answers unrelated to the programming language.
UPDATE:
It is not possible to access the Engine outside of cycle()
In your example above, std::string text = Engine::getText(); is the code you want to remember from one cycle but execute in the next. You can save it for later execution. For example - using C++11 you could use a lambda to wrap the test into a simple function specified inline.
There are two options with you:
If the library that you have can be used synchronously or using c++11 futures like facility (which can indicate the readyness of the result) then in your test case you can do something as below
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (!Engine::isResultReady());
//read the value
assert(Engine::getText() == "WHATEVERVALUEYOUEXPECT");
}
If you dont have the above the best you can do have a timeout (this is not a good option though because you may have spurious failures):
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (Engine::getText() != "WHATEVERVALUEYOUEXPECT") {
wait(1 millisec);
if (total_wait_time > 1 sec) // you can put whatever max time
assert(0);
}
}

embedded Lua C++ : how can i load multiple lua modules from C++ side

in my application I would like to load a base library in Lua before loading the lua script.
example:
testLib.lua
A = 5
B = 6
function foo(a,b)
return a+b
end
test.lua
c = foo(A,B)
In my C++ module I would like to do something like this
// load the lib
luaL_loadbuffer(L, libText, libSize, "testLib");
// run it so that the globals are known
lua_pcall(L,0,0,0);
// load the main script that uses the lib function and variables
luaL_loadbuffer(L, progText, progSize, "testLib");
// run it
lua_pcall(L,0,0,0);
here I get an error that the function 'foo' is not known
Is there a way to load multiple Lua modules on the same lua state ?
thanks for the help in advance
you would need to bind the function foo first.
http://lua-users.org/wiki/BindingCodeToLua
shows how to do it on an example where they bind c math functions

embedded Lua loading modules programmatically (C++)

I am embedding Lua in a C++ application.
I have some modules (for now, simple .lua scripts) that I want to load programmatically, as the engine is being started, so that when the engine starts, the module(s) is/are available to scripts without them having to include a require 'xxx' at the top of the script.
In order to do this, I need to be able to programmatically (i.e. C++ end), ask the engine to load the modules, as part of the initialisation (or shortly thereafter).
Anyone knows how I can do this?
Hmm, I just use the simple approach: My C++ code just calls Lua's require function to pre-load the Lua scripts I want preloaded!
// funky = require ("funky")
//
lua_getfield (L, LUA_GLOBALSINDEX, "require"); // function
lua_pushstring (L, "funky"); // arg 0: module name
err = lua_pcall (L, 1, 1, 0);
// store funky module table in global var
lua_setfield (L, LUA_GLOBALSINDEX, "funky");
// ... later maybe handle a non-zero value of "err"
// (I actually use a helper function instead of lua_pcall
// that throws a C++ exception in the case of an error)
If you've got multiple modules to load, of course, put it in a loop... :)
The easiest way is to add and edit a copy of linit.c to your project.

How does one get the instance of a Ruby class running in the current RB file? (Embedding Ruby in C++)

I have embedded Ruby inside my C++ application. I have generated the bindings using SWIG.
Basically, I run the ruby file and then Ruby takes over and calls my C++ class.
Based on my previous question, I would like to get the current instance of the class that is defined in the ruby file back to the C++ class so that I may execute instance methods.
I execute the ruby file as follows:
rb_eval_string_protect(<ruby script string>, &status );
rb_funcall(Qnil, rb_intern("main"), 0);
The global main method in the script creates an instance of the defined class in the file. That's the instance I am after.
If I have to, I will add a parameter or another function to pass the instance back, however, I'm not sure how to define that in C++ so that when SWIG generates the binding, it all works ok.
Any help would be appreciated.
Previous Question: Calling Ruby class methods from C++
The C api for ruby does its best to preserve ruby's functional nature, so rb_eval_string_protect() returns the VALUE of the last line of the script given, and rb_funcall() returns the VALUE of the last line of the method invoked.
So the trick is really to think of it as how would you get that instance value in pure ruby? If it's just the return value of main, like
# I'm a ruby script!
main_retval = main()
Then capturing the return value in C is similar:
// I'm some C (or C++) code
VALUE main_retval;
// ...
rb_eval_string_protect("...", &status);
main_retval = rb_funcall(Qnil, rb_intern("main"), 0);
And would give you a reference to the ruby object returned by main.
You can use this object as normal, calling methods and the like
VALUE main_retval_as_string = rb_funcall(main_retval, rb_intern("to_s"), 0);