ChaiScript 3.0.0

ChaiScript Documentation

ChaiScript is a scripting language designed specifically for integration with C++. It provides seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.

The parts of the ChaiScript API that the average user will be concerned with are contained in the chaiscript namespace and the chaiscript::ChaiScript class.

The end user parts of the API are extremely simple both in size and ease of use.

Currently, all source control and project management aspects of ChaiScript occur on github.


See also:
chaiscript
chaiscript::ChaiScript
ChaiScript Language Keyword Reference
ChaiScript Language In-Place Creation Reference
ChaiScript Language Object Model Reference
http://www.chaiscript.com
http://www.github.com/ChaiScript/ChaiScript

Getting Started

Basics

Basic simple example:

 #include <chaiscript/chaiscript.hpp>
 
 double function(int i, double j)
 {
   return i * j;
 }

 int main()
 {
   chaiscript::ChaiScript chai;
   chai.add(&function, "function");

   double d = chai.eval<double>("function(3, 4.75);");
 } 

Evaluating Scripts

Scripts can be evaluated with the () operator, eval method or eval_file method.

() Operator

operator() can be used as a handy shortcut for evaluating ChaiScript snippets.

 chaiscript::ChaiScript chai;
 chai("print(\"hello world\")");
See also:
chaiscript::ChaiScript::operator()(const std::string &)

Method 'eval'

The eval method is somewhat more verbose and can be used to get typesafely return values from the script.

 chaiscript::ChaiScript chai;
 chai.eval("callsomefunc()");
 int result = chai.eval<int>("1 + 3");
 // result now equals 4
See also:
chaiscript::ChaiScript::eval

Method 'eval_file'

The 'eval_file' method loads a file from disk and executes the script in it

 chaiscript::ChaiScript chai;
 chai.eval_file("myfile.chai");
 std::string result = chai.eval_file<std::string>("myfile.chai") // extract the last value returned from the file
See also:
chaiscript::ChaiScript::eval_file

Adding Items to ChaiScript

ChaiScript supports 4 basic things that can be added: objects, functions, type infos and Modules

Adding Objects

Named objects can be created with the #var function.

 using namespace chaiscript;
 ChaiScript chai;
 int i = 5;
 chai.add(var(i), "i");
 chai("print(i)");

Immutable objects can be created with the chaiscript::const_var function.

 chai.add(const_var(i), "i");
 chai("i = 5"); // exception throw, cannot assign const var

Named variables can only be accessed from the context they are created in. If you want a global variable, it must be const, and created with the chaiscript::ChaiScript::add_global_const function.

 chai.add_global_const(const_var(i), "i");
 chai("def somefun() { print(i); }; sumfun();");

Adding Functions

Functions, methods and members are all added using the same function: chaiscript::fun.

 using namespace chaiscript;
 
 class MyClass {
   public:
     int memberdata;
     void method();
     void method2(int);
     static void staticmethod();
     void overloadedmethod();
     void overloadedmethod(const std::string &);
 };
 
 ChaiScript chai;
 chai.add(fun(&MyClass::memberdata), "memberdata");
 chai.add(fun(&MyClass::method), "method");
 chai.add(fun(&MyClass::staticmethod), "staticmethod");

Overloaded methods will need some help, to hint the compiler as to which overload you want:

 chai.add(fun<void (MyClass::*)()>(&MyClass::overloadedmethod), "overloadedmethod"));
 chai.add(fun<void (MyClass::*)(const std::string &)>(&MyClass::overloadedmethod, "overloadedmethod"));

There are also shortcuts built into chaiscript::fun for binding up to the first two parameters of the function.

 MyClass obj;
 chai.add(fun(&MyClass::method, &obj), "method");
 chai("method()"); // equiv to obj.method()
 chai.add(fun(&MyClass::method2, &obj, 3), "method2");
 chai("method2()"); // equiv to obj.method2(3)

Adding Type Info

ChaiScript will automatically support any type implicitly provided to it in the form of objects and function parameters / return types. However, it can be nice to let ChaiScript know more details about the types you are giving it. For instance, the "clone" functionality cannot work unless there is a copy constructor registered and the name of the type is known (so that ChaiScript can look up the copy constructor).

Continuing with the example "MyClass" from above:

 chai.add(user_type<MyClass>(), "MyClass");

Adding Modules

Modules are holders for collections of ChaiScript registrations.

 ModulePtr module = get_sum_module();
 chai.add(module);
See also:
chaiscript::Module

Class Helper Macro

Much of the work of adding new classes to ChaiScript can be reduced with the help of the CHAISCRIPT_CLASS helper macro.

 class Test
 {
   public:
     void function() {}
     std::string function2() { return "Function2"; }
     void function3() {}
     std::string functionOverload(double) { return "double"; }
     std::string functionOverload(int) { return "int"; }
 };

 int main()
 {

   chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());

   CHAISCRIPT_CLASS( m, 
       Test,
       (Test ())
       (Test (const Test &)),
       ((function))
       ((function2))
       ((function3))
       ((functionOverload)(std::string (Test::*)(double)))
       ((functionOverload)(std::string (Test::*)(int)))
       ((operator=))
     );
 
   chaiscript::ChaiScript chai;
   chai.add(m);
 }
See also:
Adding Modules

Pointer / Object Conversions

As much as possible, ChaiScript attempts to convert between &, *, const &, const *, boost::shared_ptr<T>, boost::shared_ptr<const T>, boost::reference_wrapper<T>, boost::reference_wrapper<const T> and value types automatically.

If a var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting). Const may be added, but never removed.

The take away is that you can pretty much expect function calls to Just Work when you need them to.

 void fun1(const int *);
 void fun2(int *);
 void fun3(int);
 void fun4(int &);
 void fun5(const int &);
 void fun5(boost::shared_ptr<int>);
 void fun6(boost::shared_ptr<const int>);
 void fun7(const boost::shared_ptr<int> &);
 void fun8(const boost::shared_ptr<const int> &);
 void fun9(boost::reference_wrapper<int>);
 void fun10(boost::reference_wrapper<const int>);

 int main()
 {
   using namespace chaiscript
   chaiscript::ChaiScript chai;
   chai.add(fun(fun1), "fun1");
   chai.add(fun(fun2), "fun2");
   chai.add(fun(fun3), "fun3");
   chai.add(fun(fun4), "fun4");
   chai.add(fun(fun5), "fun5");
   chai.add(fun(fun6), "fun6");
   chai.add(fun(fun7), "fun7");
   chai.add(fun(fun8), "fun8");
   chai.add(fun(fun9), "fun9");
   chai.add(fun(fun10), "fun10");

   chai("var i = 10;");
   chai("fun1(i)");
   chai("fun2(i)");
   chai("fun3(i)");
   chai("fun4(i)");
   chai("fun5(i)");
   chai("fun6(i)");
   chai("fun7(i)");
   chai("fun8(i)");
   chai("fun9(i)");
   chai("fun10(i)");
 }  

See the unit test unittests/boxed_cast_test.cpp for a complete breakdown of the automatic casts that available and tested.


Base Classes

ChaiScript supports handling of passing a derived class object to a function expecting a base class object. For the process to work, the base/derived relationship must be registered with the engine.

 class Base {};
 class Derived : public Base {};
 void myfunction(Base *b);

 int main()
 {
   chaiscript::ChaiScript chai;
   chai.add(chaiscript::base_class<Base, Derived>());
   Derived d;
   chai.add(chaiscript::var(&d), "d");
   chai.add(chaiscript::fun(&myfunction), "myfunction");
   chai("myfunction(d)");
 }

Function Objects

Functions are first class objects in Chaiscript and ChaiScript supports automatic conversion between ChaiScript functions and boost::function objects.

 void callafunc(const boost::function<void (const std::string &)> &t_func)
 {
   t_func("bob");
 }
 
 int main()
 {
   chaiscript::ChaiScript chai;
   chai.add(chaiscript::fun(&callafunc), "callafunc");
   chai("callafunc(fun(x) { print(x); })"); // pass a lambda function to the registered function
                                            // which expects a typed boost::function

   boost::function<void ()> f = chai.eval<boost::function<void ()> >("dump_system");
   f(); // call the ChaiScript function dump_system, from C++
 }

Threading

Thread safety is automatically handled within the ChaiScript system. Objects can be added and scripts executed from multiple threads. For each thread that executes scripts, a new context is created and managed by the engine.

Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.

Disabling thread safety increases performance and removes the requirement for boost_threads.


Exception Handling

Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in ChaiScript.

 void throwexception()
 {
   throw std::runtime_error("err");
 }
 
 int main()
 {
   chaiscript::ChaiScript chai;
   chai.add(chaiscript::fun(&throwexception), "throwexception");
   chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
 
   try {
     chai("throw(1)");
   } catch (chaiscript::Boxed_Value bv) {
     int i = chaiscript::boxed_cast<int>(bv);
     // i == 1
   }
 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator