Page tree
Skip to end of metadata
Go to start of metadata

 

You must have known how to bind a function or an attribute to an existing class through "registerMethod" and "registerProperty", accordingly, using JSAPI. 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.
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:
        function testEvent()
        {
//            plugin().testEvent();
            var TestObj = plugin().TestObj;
            var t = new TestObj();
            t.x = 3;
            t.add(4);
            var t2 = new TestObj(2);
            t2.add(3);
            alert('should be 7, 5: ' + t.x + ', ' + t2.x);
        }
  • No labels