VR-Forces Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Add Lua Function (addLuaFunction)

Table of Contents

The Lua Bind Function example demonstrates the following:

Binding New Functions To Lua

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.

How to Run the Example

Lua Scripting Documents

Documentation of Lua functions for scripted tasks has its own help system.

Plugin Entry Points

/*******************************************************************************
** Copyright (c) 2012 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
//VR-Forces includes
#include "vrfLua/table_policy.hpp"
#include "luabind/out_value_policy.hpp"
// Example of user defined class to be used in Lua scripts.
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;
}
};
class AddLuaFunctionInterfaceExtension : public DtLuaScriptInterfaceExtension
{
public:
AddLuaFunctionInterfaceExtension()
{
}
virtual ~AddLuaFunctionInterfaceExtension() override {
}
// Creator function.
static DtLuaScriptInterfaceExtension* create(void* usr)
{
// In this example, the usr pointer is unused.
return new AddLuaFunctionInterfaceExtension;
}
//-------------------
// Functions for Lua API
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;
}
virtual void bindLuaFunctions(DtLocalObject* entity, const DtString& scriptId, lua_State* L) override
{
// Since this initialization gets called twice in some instances
// (due to Lua table changes when loading a scenario)
// check to make sure this is not already initialized
if (alreadyInitialized(L, "myModule"))
{
return;
}
myEntity = entity;
luabind::module(L)
[
// This luabind code defines a user class in Lua, and member functions in the class.
// Below, an entry will be made in the Lua global symbol table (with key = "myModule") and given the value
// "this", i.e. a pointer to this AddLuaFunctionInterfaceExtension object.
// Thus by writing Lua code
// myModule:luaExamplePrintMessage(message)
// you run the member function above.
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))
// The multiple return function requires you to specify which arguments are used to return.
// Here, the indexes start at _2 for the first argument in the function. Our sample function
// has the first out value in the argument slot _3. We also have a second out argument at slot
// _4 so we need to use the + with the two out values. It is recommended that if you want in values
// to also be out values, you make separate arguments for each in and each out value.
.def("luaExampleListReturn", &AddLuaFunctionInterfaceExtension::listReturnInTable,
luabind::copy_table(luabind::result))
.def("luaExampleTableReturn", &AddLuaFunctionInterfaceExtension::tableReturn)
// The bindLuaFunctions function is also used here to define another user class
// corresponding to the C++ myClass declared above. There is no entry made in the
// global symbol table for an object of this class. Instead, a Lua script can use
// a constructor to make one and then call member functions on it.
,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)
];
// Create an entry in the Lua global symbol table with key value "myModule".
// Its value is a (pointer to an) the this object, which is a
// AddLuaFunctionInterfaceExtension.
luabind::globals(L)["myModule"] = this;
}
protected:
DtLocalObject* myEntity;
};
extern "C" {
{
info.pluginName = "addLuaFunction";
info.pluginDescription = "An example of how to add a lua script function";
info.pluginVersion = "1.00";
info.pluginCreator = "MAK Technologies";
info.pluginCreatorEmail = "sales@mak.com";
info.pluginContactWebPage = "www.mak.com";
info.pluginContactMailingAddress = "10 Fawcett Street, Suite 204, Cambridge, MA 02138 USA";
info.pluginContactPhone = "(617) 876 8085";
}
DT_VRF_DLL_PLUGIN bool DtPostInitializeVrfPlugin(DtCgf* cgf)
{
DtLuaScriptInterfaceImpl::addLuaScriptInterfaceExtension(AddLuaFunctionInterfaceExtension::create, 0);
return true;
}
DT_VRF_DLL_PLUGIN void DtUnloadVrfPlugin()
{
DtLuaScriptInterfaceImpl::removeLuaScriptInterfaceExtension(AddLuaFunctionInterfaceExtension::create, 0);
}
}

Document ID: Generated on Thu Oct 23 22:29:17 EDT 2025 from SVN revision 280951
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)