Lua encapsulation class - c++

I am actually trying to create a class in C++ to encapsulate calls of Lua, actually trying to encapsulate a function to load a Lua script on the constructor, but the main problem is when I try to make a function call of the Lua script I can't find how to store the multiple returns value and how to correctly push all the arguments.
I'm trying to find an idea of the implementaion of a function who call a lua fonction with any number of any type of parameter, (the function will push arguments and call the function, but i dont want dynamic cast for example to know if i have to "lua_pushnumber" or push string for example.

You could try to accept an array of some type of variant class in your constructor, and use their type to determine how to pump them into Lua. On the other hand, there is really only two types that are interchangeable between C/C++ and Lua: string and number/double. A possible solution is to give pass in an array of strings (or a char** and an int, if you prefer), passing in your doubles as strings as well.
You could then do your loadstring() call by appending a string representation of your string or double after the string "return ". When you execute the function pushed to the stack by loadstring(), the lua engine will push your variable (string or double with appropriate type) to the lua stack. You would have the overhead of string-parsing your doubles, but if you were dying for speed I bet you would be coding purely in C++ anyways :) The advantage of this method is that you could actually pass in a function this way too: (i.e. "return function() print("hello"); end")

Related

Passing function pointer with or without &

I'm currently learning game development with c++ in Unreal Engine and I came across the function that takes a function pointer as an input:
InputHandle->BindAction("Grab",IE_Pressed, this, &UGrabber::Grab);
From basic C++ I know that in passing a function pointer as an attribute (UGrabber::Grab) - & is optional, however UEngine complains with the following error code if I omit the &:
error C3867: 'UGrabber::Grab': non-standard syntax; use '&' to create a pointer to member
Could someone explain why?
BindAction function declaration looks like this:
FInputActionBinding& BindAction( const FName ActionName, const EInputEvent KeyEvent, UserClass* Object, typename FInputActionHandlerSignature::TUObjectMethodDelegate< UserClass >::FMethodPtr Func )
The BindAction function makes use of a Dynamic Multicast Delegate.
They are one of Unreal's ways of having callback functions. In this case, they rely not just on calling a function, but calling a specific object's function. This is why you need to bass the third parameter (in this example, the parameter is this).
What it's saying is, when the input action is IE_Pressed, call the UGrabber function Grab on object this (this has to be a UGrabber instance of course). This is why it's a pointer to the method. It actually utilizes Unreal's reflection system to find the method on the object. So the this object needs to be UObject, otherwise you can't call a funciton on an object by name in C++.
For more info on this, search for "unreal delegates" and "unreal reflection" in your search engine of choice. Using them is quite easy, and it's not necessary to understand the reflection system to reliably use them. Just don't forget to bind and unbind at the appropriate times.
p.s. You can get quite in depth in this subject of callbacks you want. There are other delegate types that don't rely on reflection, for example non-dynamic delegates, that can bind to lambda functions, and or a more familiar if you're coming from a pure C++ background, where commonly a void* opaque is used, expected to be cast to the needed class pointer.

call Lua function from C++ conditionally

I am using Lua to write scipts and embed them in C++. I use LuaBridge in this process.
In my Lua script, I have some variables which need to be retrieved at first for usage in C++, besides, I have a very simple function:
run = function()
print ("state is on!")
end
This function, however, is only called under a specific condition. i.e. only called when a "true" is obtained from C++ codes after a series of complicated calculations.
Limited by my Lua and LuaBridge knowledge, what I know is: after I do
loadscript(L, "script.lua")
lua_pcall(L,0,0,0)
I can read out variables and functions from Lua script by using
LuaRef blabla = getGlobal(L, "blabla")
But now, I need to read out variables and use them at first, then in a member function
LuaRunner::LuaRun(){}
defined in a separate C++ class
class LuaRunner
the condition will be obatined and this run() function will be called if the condition is "true". It would be best to call this run() function right in the C++ member function
LuaRunner::LuaRun(){}
due to restriction of further processing.
Therefore, I was wondering whether this would be possible:
Read out the function using
LuaRef run = getGlobal(L, "run")
together with other variables at the beginning and "save" this run() function somewhere in C++ codes (perhaps as a class member function), and then the run() function can be called later on by a pointer or an object in the same class. Would this be possible? If possible, how to do it? Or any other good ideas?
It's possible to store luabridge::LuaRef's in C++ to call them later just as you normally call any other function. Though sometimes there's no need to store LuaRef's anywhere. Once you load the script, all functions stay in your lua_State, unless you set them to nil or override them by loading another script which uses the same names for functions. You can get them by using getGlobal function. If your Lua function takes arguments, you can pass them, using LuaRef's operator() like this:
if(...) { // your call condition
LuaRef f = getGlobal(L, "someFunction");
f(arg1, arg2, ...); // if your function takes no arguments, just use f();
}

Calling a function or method by reflection in C/C++

I am just going through a problem that I haven't before in C/C++, and I have no idea how to solve it. Reflection. I need to call a function or method by a string that was given by the user. Not just this, I also need to give the function or method some parameters and get its result if any.
Imagine the user has typed printSomething.
I need to evaluate "printSomething"(paramA, paramB). Of course, the function or method T printSomething() is defined.
How is the best way I can do it?
Use a structure mapping from strings to pointers to functions or methods (member functions).
C++ doesn't provide such a structure; you will have to build it yourself, passing in the name-strings and the pointers. Conversion of parameters and return values to and from strings also needs to be implemented. The language has no conventions or ideas about how this is to be done, so you must specify it.

Convert std::string to existing function with parameters in C++

I've got an implemented function MyFunc(int, double, string) in my project. How can I call this function with necessary parameters having its string representation, for example
std::string str = "MyFunc(2, 3.12, \"Lemon Juice\")";
And what about the standard functions, for example, how can I call time() having std::string "time()"?
Ok, here's more detailed task.
I've got a map <string, Data>
Data is a class-wrapper with many childs. When I call Data.GetValue() method, it returns a std::string, depending of child class inner data. One of Data childs must return the string representation of int, another - the string representation of double, and the last one - the string representation of current date and time. Here's the problem - I don't know how to call the standard function ctime() for getting information from one of Data childs.
You cannot in general execute code in C++ whose source is contained in a string. Probably the most compelling motivation for this is so that a C++ implementation is not required to have a C++ compiler on the machine that the code runs on, although there is more to it than just that.
You may be able to do it for specific cases. That could be:
Platform-specific, for example:
Wrap the source up in some boilerplate, then either call the compiler externally, link against it, or embed it in your program. This gives you a program or library.
Run that new program externally, or dynamically link against that library.
Input-specific, for example:
You could parse a function call to a particular known function, with literals as arguments, relatively easily without needing a complete C++ compiler. Get the argument values out into variables and call the function. But if you're going to do that, you could specify a more easily parsable format for the string, than one that looks like a C++ function call.
It sounds as though in your task you have a string that is one of:
a representation of an int
a representation of a double
a representation of a date and time.
You don't say what you want to do with this string, but whatever that is you probably need to (a) examine the string to find out which of the three it is, and then (b) do something appropriate to that format. Better, you could give the derived class the responsibility of returning the same representation no matter which of the three GetValue() returns. For example, if what you really want is seconds since 1970, add a GetSecondsSinceEpoc function, and implement it differently in each class.
As mentioned by others, C++ in itself is not able to do that. However external frameworks can help you.
ROOT (used at CERN) provides reflection for C++ along with an interpreter. You will be able to execute/interpret a method call or a macro written in C++ from within your code.
You can not do that using C++.

Passing existing C++ objects to Lua and calling the passed objects' member functions

I'm working on a little simulation project which uses Lua to drive the behavior of individual units (ants) and using Luabind to glue the C++ and Lua sides together. Each individual ant (there are different types, derived from the base class Ant) has a Run() function, which calls the appropriate script; the script then carries out whatever actions need to be taken, calling the exposed class functions and possibly free functions. I've gotten the Run function (in C++) to successfully execute the matching Run function in the Lua script (which just prints some text at the moment).
void AntQueen::Run()
{
lua->GetObject("QueenRun")(GetID());
}
lua is just a manager class which retrieves the function from the script. The above is calling the following in a Lua file:
function QueenRun(ID)
print("The Queen is running!")
print(ID)
end
And Luabind registration looks like this for the AntQueen class:
void Register(lua_State *luaState)
{
using namespace luabind;
module(luaState)
[
class_<AntQueen, Ant>("AntQueen")
.def("Eat", &AntQueen::Eat)
.def("ExtractLarvae", &AntQueen::ExtractLarvae)
.def("GetMaxLarvaeProduced", &AntQueen::GetMaxLarvaeProduced)
.def("GetNumAvailLarvae", &AntQueen::GetNumAvailLarvae)
];
}
The way it's set up now, ants are created, removed, and found through a simple factory/manager. Each ant can be retrieved by calling static Ant* AntFactory::GetAntByID(const int ID) which just finds the ant in a hash map and returns a pointer to the ant. What I'm trying to do is get Lua to be able to do something like the following:
function QueenRun(ID)
ant = GetAntByID(ID)
larvae = ant:GetNumAvailLarvae()
print(larvae)
ant:Eat()
end
The above is just a made up example, but hopefully it shows what I'm trying to achieve. I don't want Lua to garbage collect the objects, because they are managed already on the C++ side. While testing everything out, any attempt to do the following:
ant = GetAntByID(ID)
in Lua resulted in abort() being called and the program crashing and burning.
R6010
-abort() has been called
I just seem to be missing something with how everything gets shuttled back and forth (this is my first foray into gluing Lua and C++ together beyond toy programs). I'm pretty sure passing a plain pointer isn't the way to do it; lightuserdata seems to be what I'm looking for, but it also has a bunch of restrictions.
So to sum up: What is going on here that causes abort to be called and how can I use Luabind/the Lua C API to get a pointer to a C++ object passed to Lua and call member functions on that pointer as if it were an object (without letting Lua garbage collect it)?
The solution to this problem seemed to be tied to the AntFactory class/member functions being static. As soon as I switched from registering and using this:
//C++
static int AntFactory::CreateAnt(foo, bar)
{}
//Lua
factory:CreateAnt(foo, bar)
to an instantiated object and regular member functions like this:
//C++
int AntFactory::CreateAnt(foo, bar)
{}
//Lua
factory:CreateAnt(foo, bar)
everything worked with no problems at all (after also pushing the factory to the global table). I think the reason for this is that trying to call static member functions on a non-instantiated C++ object fails due to Lua (or Luabind?) not being able to have an object to query for calls.