SourceForge.net Logo

eval_example.cpp

An example of using eval

// Point.hpp
// An extremely simple point class.
class Point
{
public:
    Point()
      : _x(0), _y(0)
    {
    }

    Point(int x, int y)
      : _x(x), _y(y)
    {
    }

    int get_x() const
    {
        return _x;
    }

    int get_y() const
    {
        return _y;
    }

    void set_x(int x)
    {
        _x = x;
    }

    void set_y(int y)
    {
        _y = y;
    }

    void add_to_this(const Point& other)
    {
        _x += other._x;
        _y += other._y;
    }

    // A somewhat artificial overload; note the corresponding
    // eval header syntax.
    void add_to_this(int x, int y)
    {
        _x += x;
        _y += y;
    }

private:
    int _x;
    int _y;

    friend Point add_points(Point& a, Point& b);
};




inline Point add_points(Point& a, Point& b)
{
    return Point(a._x + b._x, a._y + b._y);
}



// A somewhat artificial inheritance structure; note the corresponding
// eval header syntax.
class ThreeDimPoint : public Point
{
public:
    ThreeDimPoint(int x, int y, int z)
      : Point(x, y), _z(z)
    {
    }

    ThreeDimPoint()
      : Point(), _z(0)
    {
    }

    int get_z() const
    {
        return _z;
    }

    void set_z(int z)
    {
        _z = z;
    }

private:
    int _z;
};


// eval_example_header.ehpp

// Defines the basic types (e.g. int, double, ...)
#include "eval_headers/basic_types.ehpp"

// These headers are nowhere near complete.
#include "eval_headers/string.ehpp"
#include "eval_headers/ostream.ehpp"


EVAL_REGISTER_TYPE(Point)
    EVAL_REGISTER_CONSTRUCTOR(())          // default constructor
    EVAL_REGISTER_CONSTRUCTOR((int, int))
    EVAL_REGISTER_CONSTRUCTOR((Point))     // copy constructor
    EVAL_REGISTER_METHOD(get_x)
    EVAL_REGISTER_METHOD(get_y)
    EVAL_REGISTER_METHOD(set_x)
    EVAL_REGISTER_METHOD(set_y)
    EVAL_REGISTER_METHOD_OVERLOADED(void, (const Point&), add_to_this)
    EVAL_REGISTER_METHOD_OVERLOADED(void, (int, int), add_to_this)
EVAL_END_TYPE


EVAL_REGISTER_FUNCTION(add_points)


EVAL_REGISTER_TYPE(ThreeDimPoint)
    // Note: EVAL_INHERIT_FROM semantically really means "implements".
    // Inheritance hierarchy is irrelevant; however, this class must
    // implement/inherit all the methods (excluding constructors) in Point, or
    // compilation will fail (in C++ it is possible to create a subclass which
    // does not implemented all the methods of its superclass exactly).
    // If this class overwrites methods from the base class, you can list
    // them explicitly, but that's not necessary.
    EVAL_INHERIT_FROM(Point)

    EVAL_REGISTER_CONSTRUCTOR(())
    EVAL_REGISTER_CONSTRUCTOR((int, int, int))
    EVAL_REGISTER_CONSTRUCTOR((ThreeDimPoint))
    EVAL_REGISTER_METHOD(get_z)
    EVAL_REGISTER_METHOD(set_z)
EVAL_END_TYPE


// Note that it is possible to register functions/methods/types
// with a different name than in their C++ source (so that the
// scripts would be able to refer to an alias name).
// eval_example_script.epp

// std::cout, point1 and point2 come in as arguments

// call operator<< function
std::cout << "Hello world from an eval script" << "\n";

val point3; // Declare new variable (accessible from calling program).
            // All variables have type val; declarations go on their own line.
point3 = Point(point1.get_x(), point2.get_y());

// modify an argument passed in
point2.add_to_this(point3);
point2.add_to_this(1, 2);

val point_rv;
point_rv = add_points(point1, ThreeDimPoint(8, 9, 6)); // adding in 2D only!


// Note:
val temp;
temp = 3;      // const int
temp = int(3); // int

// eval_example.cpp

#include <string>
#include <iostream>
#include <assert.h>

// The eval header defines 2 functions, eval_file and eval (takes const char *)
#include "eval.hpp"

// The val class is a generic class for wrapping arbitary instances/primitives.
#include "val.hpp"

// A plain old c++ class, serving as an example.
#include "Point.hpp"

// The EVAL_INCLUDE_FILE1 is the eval header that determines which
// functions/methods/constructors the scripts have access to.
#define EVAL_INCLUDE_FILE1 "eval_example_header.ehpp"

// Some preprocessor magic happens at this point. Suffices to say that
// you now have a class deriving from eval::execution_context, called
// MyExecContext. This custom excecution context knows about
// functions/methods/constructors as per EVAL_INCLUDE_FILE1.
// (You can create more than 1 execution context.)
#define EVAL_EXECUTION_CONTEXT_NAME MyExecContext
#include "create_execution_context_definition.hpp"



int main()
{
    MyExecContext e;   // Create our custom execution context.
    e.register_all();  // Register all functions/methods/constructors. In some
                       // circumstances, the execution context can be used
                       // without this call.
    
    // Make std::cout available to the script (in future library versions,
    // this may be done in the appropriate eval standard header).
    e["std::cout"] = eval::val(&std::cout, eval::UNMANAGED_PTR);

    // make some Points available to the script
    e["point1"] = eval::val(new Point(4, 5), eval::TRANSFER_OWNERSHIP);
    Point point2(6, 7);
    e["point2"] = eval::val(&point2, eval::UNMANAGED_PTR);

    // execute our example script (the script is in the same directory;
    // specifying a more complete path just helps the automated testing system)
    eval_file(e, "../examples/eval_example_script.epp");
    
    // We have access to variables defined in the script.
    Point *point_rv = e.extended_val_cast_ptr<Point>(e["point_rv"]);
    assert(point_rv->get_x() == 12);
    assert(point_rv->get_y() == 14);

    // The script also modified existing objects (arguments)
    assert(point2.get_x() == 11);
    assert(point2.get_y() == 16);

    // Note that various casting methods exist, allowing you to attempt
    // to convert return values to a particular type (or just get a string
    // or int representation, if possible).

    return 0;
}

Generated on Sat Sep 20 20:02:34 2008 for eval by  doxygen 1.5.6