Cpp Convenient Lua Wrapper Class


The purpose for this wrapper is providing convenient mechanisms in C++ for exposing methods and calling script functions. All a C++ programmer needs is to inherit from a particular class, then services are provided for loading a Lua script, exposing methods with any signatur, and calling script functions.

Following example shows how a Lua script is embedded into a class. For more details contact Yag2002 group at http://yag2002.sourceforge.net

Have fun.

--boto

Lua Script

print( "in Lua: starting script" )
print( "in Lua: calling exposed exposedMethods ..." )
-- exposed method1: [ std::string, float ] exposedMethod1(int, float)
a, b = testScript.exposedMethod1(42, 0.42)
print("in Lua:", a, b)
-- exposed method2: void exposedMethod2( int, std::string)
testScript.exposedMethod2( 65, "Hello" )
print("in Lua: exposed exposedMethods have been called")
-- callable script function ( from entity )
function scriptFcn1(x) 
 print("in Lua: scriptFcn1 has been called with argument: ", x)
end
function scriptFcn2(x, y) 
 print("in Lua: scriptFcn2 has been called with arguments: ", x, ", ", y)
 return "result: ", x * 2, y *2
end

C++ Code

#include "vrc_script.h"
//! Class for embedding a test script
class EnTestScript : public vrc::BaseScript< EnTestScript >
{
 public:
 EnTestScript( const std::string& scriptfile );
 virtual ~EnTestScript();
 //! Start loading and executing the test script
 void start();
 //! test for an exposed method
 void exposedMethod1( const Params& arguments, Params& returnvalues );
 //! test for an exposed method
 void exposedMethod2( const Params& arguments, Params& returnvalues );
 protected:
 //! Script file
 std::string _scriptFile;
};
EnTestScript::EnTestScript( const std::string& scriptfile )
 _scriptFile( scriptfile )
{
}
EnTestScript::~EnTestScript()
{
}
void EnTestScript::start()
{
 try
 {
 // load script file and scope all exposed methods with 'testScript'
 loadScript( "testScript", _scriptFile );
 // expose methods
 
 Params arguments;
 Params returnsvalues;
 //Note: for adding a parameter type into a Params container one can define an initial value ( which is normally ignored ).
 // it is important that the compiler can deduce the 'add' method by knowing the type which is added. 
 // currently int, float, double, and std::string types are supported.
 // take also care on the order you define the arguments or return values.
 // expose method 1 having the pseudo-signatur: [ std::string, float ] method1( int, float )
 {
 arguments.add( 0 ); // here just pass an int variable or a constant int, we take 0
 arguments.add( 0.0f ); // here just pass a float variable or a constant float, we take 0.0f
 returnsvalues.add( std::string() );
 returnsvalues.add( 0.0f );
 exposeMethod( "exposedMethod1", &EnTestScript::exposedMethod1, arguments, returnsvalues );
 }
 // some tests
 {
 size_t argumentcontainersize = arguments.size();
 assert( argumentcontainersize == 2 );
 size_t returnsvaluescontainersize = returnsvalues.size();
 assert( returnsvaluescontainersize == 2 );
 const type_info& typeofelementatindexZero = arguments.getTypeInfo( 0 );
 assert( typeofelementatindexZero == typeid( int ) );
 const type_info& typeofelementatindexOne = arguments.getTypeInfo( 1 );
 assert( typeofelementatindexOne == typeid( float ) );
 }
 
 arguments.clear();
 returnsvalues.clear();
 // expose method 2 having the pseudo-signatur: void method1( int, std::string )
 {
 arguments.add( 0 );
 arguments.add( std::string() );
 exposeMethod( "exposedMethod2", &EnTestScript::exposedMethod2, arguments );
 }
 // execute the script after exposing methods
 execute();
 // call script function scriptFcn1: void scriptFcn1( int )
 {
 Params args;
 args.add( 100.42 );
 
 // the function has no return value
 callScriptFunction( "scriptFcn1", &args );
 }
 // call script function scriptFcn2: [ std::string, int, int ] scriptFcn2( int, int )
 {
 Params args;
 args.add( 100 );
 args.add( 150 );
 Params rets;
 rets.add( std::string() );
 rets.add( 0 );
 rets.add( 0 );
 
 callScriptFunction( "scriptFcn2", &args, &rets );
 std::stringstream msg;
 msg << "in Entity: scriptFcn2 returned: " << GET_SCRIPT_PARAMVALUE( rets, 0, std::string ) << " "
 << GET_SCRIPT_PARAMVALUE( rets, 1, int ) << " " << GET_SCRIPT_PARAMVALUE( rets, 2, int );
 log_debug << msg.str() << std::endl; 
 }
 // close the script and clean up its resources
 closeScript();
 }
 catch( const ScriptingException& e )
 {
 log_error << "TestScript: error occured during script test: " << e.what() << std::endl;
 }
}
void EnTestScript::exposedMethod1( const Params& arguments, Params& returnvalues )
{
 // get parameters
 std::stringstream msg;
 msg << "in Entity: exposedMethod1( " << GET_SCRIPT_PARAMVALUE( arguments, 0, int ) << " " << GET_SCRIPT_PARAMVALUE( arguments, 1, float ) << " )";
 log_debug << msg.str() << std::endl;
 // set return values
 SET_SCRIPT_PARAMVALUE( returnvalues, 0, std::string, "returnvalue is: " );
 SET_SCRIPT_PARAMVALUE( returnvalues, 1, float, 0.12345f );
}
void EnTestScript::exposedMethod2( const Params& arguments, Params& returnvalues )
{
 std::stringstream msg;
 msg << "in Entity: exposedMethod2( " << GET_SCRIPT_PARAMVALUE( arguments, 0, int ) << ", " << GET_SCRIPT_PARAMVALUE( arguments, 1, std::string ) << " )";
 log_debug << msg.str() << std::endl;
}
int main( int argc, char** argv )
{
 EnTestScript ts( "<path>/script.lua" );
 ts.start();
 return 0;
}

Output

in Lua: starting script
in Lua: calling exposed exposedMethods ...
in Entity: exposedMethod1( 42 0.42 )
in Lua: returnvalue is: 0.12345000356436
in Entity: exposedMethod2( 65, Hello )
in Lua: exposed exposedMethods have been called
in Lua: scriptFcn1 has been called with argument: 100.42
in Lua: scriptFcn2 has been called with arguments: 100 , 150
in Entity: scriptFcn2 returned: result: 200 300

Wrapper Source Code

Files:wiki_insecure/LuaWrapper(VRC).zip C++ Wrapper code


RecentChanges · preferences
edit · history
Last edited January 6, 2007 1:34 pm GMT (diff)

AltStyle によって変換されたページ (->オリジナル) /