I have done some experiments in FireBreath to support JS binding for object construction, e.g. "new TestObj()" and made it work. I would like to share my experience with everyone in case you need to do the same thing in the future.
You must have known how to bind a function or an attribute to an existing class through "registerMethod" and "registerProperty", accordingly. The example can be found in FireBreath's auto-generated TestPlugin. To support creating a new object type, say "TestObj", you must first "registerProperty" with the name of the new class, "TestObj", and a function that returns an instance of another class "TestObjConstructor". This "TestObjConstructor" is also a JSAPIAuto-derived class and it should override the virtual function "Construct". In its "Construct" function, which is triggered each time the Javascript code calls "new TestObj()", it should return a new instance of "TestObj". This completes the support of JS object construction.
I have some experimental code based on MyTestPlugin generated by FireBreath, as shown below.
diff --git a/MyTestPluginAPI.cpp b/MyTestPluginAPI.cpp
index 8d17632..6b7a72e 100644
--- a/MyTestPluginAPI.cpp
+++ b/MyTestPluginAPI.cpp
@@ -60,6 +60,32 @@ std::string MyTestPluginAPI::get_version()
return FBSTRING_PLUGIN_VERSION;
}
+FB::variant MyTestPluginAPI::TestObjConstructor()
+{
+ return TestObjConstructor::getConstructor();
+}
+
+FB::JSAPIPtr TestObjConstructor::getConstructor()
+{
+ static FB::JSAPIPtr s_instance;
+ if (!s_instance.get()) {
+ s_instance = boost::make_shared<TestObjConstructor>();
+ }
+ return s_instance;
+}
+
+FB::variant TestObjConstructor::Construct(const std::vector<FB::variant> &args)
+{
+ boost::recursive_mutex::scoped_lock lock(m_zoneMutex);
+ if(!m_valid)
+ throw FB::object_invalidated();
+
+ if (args.size() < 1)
+ return boost::make_shared<TestObj>();
+
+ return boost::make_shared<TestObj>(args[0].convert_cast<int>());
+}
+
void MyTestPluginAPI::testEvent()
{
fire_test();
diff --git a/MyTestPluginAPI.h b/MyTestPluginAPI.h
index ee4a41b..a7dc694 100644
--- a/MyTestPluginAPI.h
+++ b/MyTestPluginAPI.h
@@ -14,6 +14,27 @@
#ifndef H_MyTestPluginAPI
#define H_MyTestPluginAPI
+class TestObj : public FB::JSAPIAuto
+{
+public:
+ TestObj(int x = 0) : m_x(x) {
+ registerMethod("add", make_method(this, &TestObj::add));
+ registerProperty("x", make_property(this, &TestObj::x, &TestObj::setX));
+ };
+ void add(int x) { m_x += x; };
+ int x() { return m_x; };
+ void setX(int x) { m_x = x; };
+private:
+ int m_x;
+};
+
+class TestObjConstructor : public FB::JSAPIAuto
+{
+public:
+ static FB::JSAPIPtr getConstructor();
+ virtual FB::variant Construct(const std::vector<FB::variant>& args);
+};
+
class MyTestPluginAPI : public FB::JSAPIAuto
{
public:
@@ -44,6 +65,11 @@ public:
registerProperty("version",
make_property(this,
&MyTestPluginAPI::get_version));
+
+ // cshu's test
+ registerProperty("TestObj",
+ make_property(this,
+ &MyTestPluginAPI::TestObjConstructor));
}
///////////////////////////////////////////////////////////////////////////////
@@ -64,6 +90,9 @@ public:
// Read-only property ${PROPERTY.ident}
std::string get_version();
+ // cshu's test
+ FB::variant TestObjConstructor();
+
// Method echo
FB::variant echo(const FB::variant& msg);
--
The JS code could be:
I hope the above is helpful and also would like to thank taxilian's help over IRC.