2015-05-18 36 views
8

bunu javascript işlevsellik eklemek ve duktape seçti istiyorum ben C++ sınıfı noktaya tutunihracat C++ sınıfı duktape için

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

    float X; 
    float Y; 

}; 

olduğunu varsayalım.

Bu sınıf javascript'te yeniden kullanılabilir mi? Ben duktape belgeleri okuyarak edilmiştir

var p = new Point(1.23, 4.56); 

söylemek ve sadece javascript içinde işlevlerini yeniden nasıl söylüyor.

cevap

10

Kişisel tavsiyem, tıpkı JavaScript’te yaptığınız gibi C++ bağlamaları oluşturmaktır.

Tek gereksinim, gerçek C++ nesnesini JavaScript nesnesine kaydetmek, bu amaçla internal properties kullanıyoruz.

Yapıcı işlevi olarak JavaScript'ten çağrılacak bir işlev oluşturmanız gerekiyor, daha sonra yalnızca prototipini doldurmanız ve bir sonlandırıcı ayarlamanız gerekiyor. Zor değil ama çok fazla kod gerektiriyordu, böylece temelde bunları kolaylaştırmak için sarıcı oluşturmak istiyorsunuz.

#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

Neden \ xff \ xffdata kullanıyorsunuz - özelliği Javascript'ten gizlemek için mi? Ayrıca, neden silinmiş bir özelliğe ihtiyacınız var - veri özelliğini nullptr olarak ayarlayamaz ve kullanabilir misiniz? – imekon

+0

Ah ... sadece dahili özellik belgelerini okuyun - bu yüzden \ xff \ xff – imekon

+0

Evet tam olarak, özür dilerim bunu açıklamayı unuttum. – markand