Cpp Convenient Lua Wrapper Class

lua-users home
wiki

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 6:34 pm GMT (diff)