To add a new function to the Lua API, it is necessary to define it in C++ and then bind it to a Lua function name. VR-Forces uses the Luabind package to do this. Information about Luabind can be found at https://www.rasterbar.com/products/luabind.html. The example code in the plugin shows how to manipulate luabind::objects and how to define C++ function arguments and returns so that they convert to Lua function arguments and returns.
Since this example is loaded as a plugin, it can be used in conjunction with the released VR-Forces application. Make sure to enable the addLuaFunction example from the launcher application.
#include "vrfLua/table_policy.hpp"
#include "luabind/out_value_policy.hpp"
class myClass
{
public:
myClass(const double x, const double y)
{
myA = x;
myB = y;
}
~myClass() {}
double myA, myB;
void setA(const double x) { myA = x; }
double a() const { return myA; }
void setB(const double x) { myB = x; }
double b() const { return myB; }
double getR() const { return sqrt(myA * myA + myB * myB); }
myClass add(const myClass& other)
{
myClass sum(this->myA + other.myA, this->myB + other.myB);
return sum;
}
};
{
public:
AddLuaFunctionInterfaceExtension()
{
}
virtual ~AddLuaFunctionInterfaceExtension() override {
}
{
return new AddLuaFunctionInterfaceExtension;
}
virtual void printMessage(const std::string& message)
{
DtWarn << myEntity->objectName().string() << ": " << message.c_str() << std::endl;
myEntity->objectConsoleInfo() << message << std::endl;
}
virtual std::string multipleReturn(bool b, int& someNumber, bool& success)
{
if (b)
{
someNumber = 40;
success = true;
}
else
{
someNumber = 10;
success = false;
}
return "return string";
}
virtual std::list<std::string> listReturnInTable(const luabind::object& inTable)
{
std::list<std::string> result;
if (luabind::type(inTable) == LUA_TTABLE)
{
luabind::iterator tblIter(inTable);
luabind::iterator endIter;
for (tblIter; tblIter != endIter; tblIter++)
{
int a = luabind::object_cast<int>(*tblIter);
std::string s = std::to_string(a);
result.push_back(s);
}
}
return result;
}
virtual luabind::object tableReturn(lua_State* L, const myClass& in)
{
luabind::object result = luabind::newtable(L);
result["a"] = in.a();
result["b"] = in.b();
return result;
}
bool alreadyInitialized(lua_State* L, const char* moduleName) const
{
luabind::object obj = luabind::globals(L)["myModule"];
if (luabind::type(obj) != LUA_TNIL)
{
return true;
}
return false;
}
{
if (alreadyInitialized(L, "myModule"))
{
return;
}
myEntity = entity;
luabind::module(L)
[
luabind::class_<AddLuaFunctionInterfaceExtension>("AddLuaFunctionInterfaceExtension")
.def("luaExamplePrintMessage",
&AddLuaFunctionInterfaceExtension::printMessage)
.def("luaExampleMultiReturn", &AddLuaFunctionInterfaceExtension::multipleReturn,
luabind::pure_out_value(boost::placeholders::_3) + luabind::pure_out_value(boost::placeholders::_4))
.def("luaExampleListReturn", &AddLuaFunctionInterfaceExtension::listReturnInTable,
luabind::copy_table(luabind::result))
.def("luaExampleTableReturn", &AddLuaFunctionInterfaceExtension::tableReturn)
,luabind::class_<myClass>("MyClass")
.def(luabind::constructor<const double, const double>())
.def("setA", &myClass::setA)
.def("getA", &myClass::a)
.def("setB", &myClass::setB)
.def("getB", &myClass::b)
.def("getR", &myClass::getR)
.def("add", &myClass::add)
];
luabind::globals(L)["myModule"] = this;
}
protected:
};
extern "C" {
{
}
{
return true;
}
{
}
}