2015-05-18 54 views
8

說我有一個C++類Point出口C++類duktape

class Point { 
public: 
    Point(); 
    Point(float x, float y); 
    ~Point(); 

    float X; 
    float Y; 

}; 

我想的JavaScript功能添加到它,並選擇duktape。

是否有可能在javascript中重用此類? 說

var p = new Point(1.23, 4.56); 

我一直在閱讀的duktape文檔,它只是說如何重用裏面的JavaScript函數。

回答

10

我的個人建議是爲它創建C++綁定,就像在JavaScript中做的一樣。

唯一需要的是將真正的C++對象保存在JavaScript對象中,爲此我們使用internal properties

您需要創建一個將從JavaScript調用的函數作爲構造函數,然後您只需填充其原型並設置終結器。這並不難,但它需要大量的代碼,所以你基本上想要創建包裝來使它們更容易。

#include <iostream> 

#include "duktape.h" 

class Point { 
public: 
    float x; 
    float y; 
}; 

/* 
* This is the point destructor 
*/ 
duk_ret_t js_Point_dtor(duk_context *ctx) 
{ 
    // The object to delete is passed as first argument instead 
    duk_get_prop_string(ctx, 0, "\xff""\xff""deleted"); 

    bool deleted = duk_to_boolean(ctx, -1); 
    duk_pop(ctx); 

    if (!deleted) { 
     duk_get_prop_string(ctx, 0, "\xff""\xff""data"); 
     delete static_cast<Point *>(duk_to_pointer(ctx, -1)); 
     duk_pop(ctx); 

     // Mark as deleted 
     duk_push_boolean(ctx, true); 
     duk_put_prop_string(ctx, 0, "\xff""\xff""deleted"); 
    } 

    return 0; 
} 

/* 
* This is Point function, constructor. Note that it can be called 
* as a standard function call, you may need to check for 
* duk_is_constructor_call to be sure that it is constructed 
* as a "new" statement. 
*/ 
duk_ret_t js_Point_ctor(duk_context *ctx) 
{ 
    // Get arguments 
    float x = duk_require_number(ctx, 0); 
    float y = duk_require_number(ctx, 1); 

    // Push special this binding to the function being constructed 
    duk_push_this(ctx); 

    // Store the underlying object 
    duk_push_pointer(ctx, new Point{x, y}); 
    duk_put_prop_string(ctx, -2, "\xff""\xff""data"); 

    // Store a boolean flag to mark the object as deleted because the destructor may be called several times 
    duk_push_boolean(ctx, false); 
    duk_put_prop_string(ctx, -2, "\xff""\xff""deleted"); 

    // Store the function destructor 
    duk_push_c_function(ctx, js_Point_dtor, 1); 
    duk_set_finalizer(ctx, -2); 

    return 0; 
} 

/* 
* Basic toString method 
*/ 
duk_ret_t js_Point_toString(duk_context *ctx) 
{ 
    duk_push_this(ctx); 
    duk_get_prop_string(ctx, -1, "\xff""\xff""data"); 
    Point *point = static_cast<Point *>(duk_to_pointer(ctx, -1)); 
    duk_pop(ctx); 
    duk_push_sprintf(ctx, "%f, %f", point->x, point->y); 

    return 1; 
} 

// methods, add more here 
const duk_function_list_entry methods[] = { 
    { "toString", js_Point_toString, 0 }, 
    { nullptr, nullptr,  0 } 
}; 

int main(void) 
{ 
    duk_context *ctx = duk_create_heap_default(); 

    // Create Point function 
    duk_push_c_function(ctx, js_Point_ctor, 2); 

    // Create a prototype with toString and all other functions 
    duk_push_object(ctx); 
    duk_put_function_list(ctx, -1, methods); 
    duk_put_prop_string(ctx, -2, "prototype"); 

    // Now store the Point function as a global 
    duk_put_global_string(ctx, "Point"); 

    if (duk_peval_string(ctx, "p = new Point(20, 40); print(p)") != 0) { 
     std::cerr << "error: " << duk_to_string(ctx, -1) << std::endl; 
     std::exit(1); 
    } 

    return 0; 
} 
+0

爲什麼你使用\ xff \ xffdata - 是爲了隱藏Javascript的屬性?另外,爲什麼你需要一個刪除的屬性 - 你可以不設置數據屬性爲nullptr並使用它? – imekon

+0

啊...只是閱讀內部屬性文檔 - 因此\ xff \ xff – imekon

+0

是的,對不起,我忘了解釋它。 – markand