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".
help/examples/stringset.cppLet'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.
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.
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
1.6.1