Binding C++ functions

Previous: Garbage collection

An important use of Flusspferd is binding C++ functions so that they are accessible from Javascript, for obvious reasons. Flusspferd provides convenient methods for doing so.

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

// For the named parameters.
using namespace flusspferd::param;

// This function (as seen from Javascript) prints its first parameter on the
// screen.
void print(flusspferd::string const &x) {
    std::cout << x << '\n';
}

// This function prints the contents of 'this' on the screen.
void print_object(flusspferd::object &o) {
    std::cout << o.call("toSource") << '\n';
}

// This function calculates exp(i) where i is an integral number.
double exp_i(int i) {
    return std::exp(i);
}

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

    flusspferd::object g = flusspferd::global();

    // Create a method of the global object (= global function) with name print
    // that calls print().
    flusspferd::create<flusspferd::function>("print", &print, _container = g);

    // Create a global function that calls exp_i().
    flusspferd::create<flusspferd::function>("exp", &exp_i, _container = g);

    flusspferd::object p = flusspferd::evaluate("Object.prototype").to_object();

    // Create a method of Object.prototype that calls print_object().
    // The difference between create<function> and create<method> is that the
    // latter passes Javascript's 'this' as parameter to the function.
    //
    // (Note that every normal object ultimately has as prototype the value of
    // Object.prototype. However create<> creates the properties with dont_enum
    // by default, so doing this is safe.)
    flusspferd::create<flusspferd::method>("print", &print_object, _container = p);

    // Print e.
    // (Note that 1.2 is rounded down to 1.)
    flusspferd::evaluate("print(exp(1.2))");

    // Print the contents of a literal object.
    flusspferd::evaluate("({a:1, b:2}).print()");
}
Note:
You can find the source in help/examples/functions1.cpp.

As you can see in the above example, you just declare your C++ functions with the type you want and Flusspferd will deal with converting the arguments automaitically from the underlying types for you. The same goes for the return values from your functions. If you've ever dealt with the Spidermonkey API directly you'll know how much of a time saver this behaviour is. (And in case you are wondering, this is achieved through C++ templates and boost meta-programming. Scary, scary meta-programming.)

If this type coercion behaviour is counter to what you need for a particular case, then you can get the raw arguments that your function was called with by defining your function as returning void and taking a single flusspferd::call_context argument:

void my_function(call_context &x) {
    // Result of the function is the number of arguments that it was called with
    x.result = x.args.size();

    if (x.args.size() > 1) {
      // Print the first argument (if there is one) to stdout
      cout << x.arg[0] << endl;
    }
}
See also:
Creating values, objects and functions

Next: Creating a Javascript class


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