Creating a Javascript class

Previous: Binding C++ functions

Other than functions, users of Flusspferd will likely want to create classes.

As a simple example, we have chosen a "set of strings".

Note:
You can find the source in help/examples/stringset.cpp

Let's begin the walk through. First, as always, the required headers.

#include <flusspferd.hpp>
#include <iostream>
#include <ostream>
#include <set>

We use the macro FLUSSPFERD_CLASS_DESCRIPTION for describing the class to Flusspferd. It takes one unnamed parameter and multiple named parameters (yes, that's possible in C++).

The first (unnamed) parameter cpp_name indicates the name of the class in the C++ source code.

Note:
FLUSSPFERD_CLASS_DESCRIPTION will create two classes: StringSet and StringSet_base.

FLUSSPFERD_CLASS_DESCRIPTION(
    StringSet,

The parameters full_name and constructor_name define the complete identifier (system-unique!) of the class respectively the name of the constructor inside the container passed to flusspferd::load_class.

    (full_name, "StringSet")
    (constructor_name, "StringSet")

With methods, we can bind Javascript method names to C++ methods.

    (methods,
        ("dump", bind, dump)
        ("add", bind, add)
        ("delete", bind, delete_)
        ("toArray", bind, to_array)))
{

Here begins the class StringSet.

public:

Below is the constructor that will be called from Javascript. Note that the first parameter has to be passed to flusspferd::native_object_base.

    StringSet(flusspferd::object const &self, flusspferd::call_context &x)
        : base_type(self)
    {

Let us notify the user that the constructor has been called successfully.

        std::cout << "Creating StringSet" << std::endl;

Now, we add the constructor parameters to the StringSet. To do so we convert the flusspferd::value parameters to std::string (via flusspferd::string).

        for (flusspferd::arguments::iterator it = x.arg.begin();
                it != x.arg.end();
                ++it) {
            data.insert((*it).to_std_string());
        }

That's the whole constructor.

    }

A few typedefs for the data types we use internally:

public:
    typedef std::set<std::string> container;
    typedef container::iterator iterator;

The first three methods should be pretty straight-forward:

    void dump() {
        std::cout << "Dumping StringSet: ";
        for (iterator it = data.begin(); it != data.end(); ++it) {
            if (it != data.begin())
                std::cout << ',';
            std::cout << *it;
        }
        std::cout << std::endl;
    }

    void add(std::string const &x) {
        data.insert(x);
    }

    void delete_(std::string const &x) {
        if (!data.erase(x))
            throw flusspferd::exception("No such element");
    }

The method to_array (or rather, toArray, as seen from Javascript) creates an array and calls Array.prototype.push to add each element from the StringSet.

    flusspferd::array to_array() {
        flusspferd::root_array result(flusspferd::create<flusspferd::array>());

        for (iterator it = data.begin(); it != data.end(); ++it) {
            result.push(*it);
        }

        return result;
    }

The finish the implementation of StringSet, we need a std::set to store the elements in.

private:
    container data;
};

The print function simply prints its parameter.

void print(flusspferd::string const &x) {
    std::cout << x << std::endl;
}

In main, we first create a flusspferd::context and then load the print function.

int main() {
    flusspferd::current_context_scope context_scope(
        flusspferd::context::create());

    flusspferd::create<flusspferd::function>(
        "print", &print,

Now (*drumrolls*), we load the class StringSet into Flusspferd.

    flusspferd::load_class<StringSet>();

And finally, we'll use StringSet from Javascript.

    flusspferd::evaluate(
        "var set = new StringSet('b', 'a', 'd');\n"
        "set.add('c');\n"
        "set.dump();\n"
        "set.delete('a'); set.delete('b');\n"
        "print('As Array: ' +  set.toArray().toSource());\n"
    );
}

That's it.

Note:
You can find the program in help/examples/stringset.cpp.

The output should be:

Creating StringSet
Dumping StringSet: a,b,c,d
As Array: ["c", "d"]
Destroying StringSet

Next: "Without macros please"


Contact us at team -AT- flusspferd -DOT- org or as described on our homepage.

Generated on Thu Feb 4 23:05:12 2010 for Flusspferd by doxygen 1.6.1