2012-01-24 14 views
8

Her ikisi de ObjectWrap'dan devralınan javascript sınıfları, VanillaOption ve NoomraEngine olarak gösterilen 2 C++ sınıfına sahibim. NoomraEngine aşağıdaki yöntemde ObjectWrap :: Unwrap'i bir Nodejs eklentisinde çağırırken doğru tip nasıl denetlenir?

, ben almak mı gerekiyor Daha önceden "sarılmış" VanillaOption:

Handle<Value> 
NoomraEngine::Price(const Arguments& args) { 
    HandleScope scope; 
    Local<Object> object = args[0]->ToObject(); // VanillaOption expected in args[0] 

    VanillaOption* equityOption = ObjectWrap::Unwrap<VanillaOption>(object); 

    Local<Number> x = Number::New(this->price(equityOption)); 
    return scope.Close(x); 
} 

Her şey gayet iyi çalışıyor dışında ben yönteme türü yanlış geçmesi halinde, ObjectWrap::Unwrap yılında düğüm çöker.

Sorumu, doğru türü args[0]'dan aldığımdan nasıl emin olabilirim?

cevap

3

DÜZENLEME: Bu çıplak V8 olandan daha iyi bir yöntem MyObject::Init olarak NanHasInstance (https://github.com/rvagg/nan#api_nan_has_instance)

kullanmaktır:

Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); 
tpl->SetClassName(NanNew<String>("MyObject")); 
... 
NanAssignPersistent(prototype, tpl); 

prototype statik olduğu üyesi, MyObject. Böyle

Kullanım: Bu bir Düğüm addon yazma benim ilk ışığı olduğunu ihtar ile

if (NanHasInstance(prototype, handle)) { 
    MyObject* obj = ObjectWrap::Unwrap<MyObject>(handle); 
    ... 
} 

, etrafta kendi wrapper ile nesnenin prototip kontrol ederek tam bu sorunu çözdü UnWrap. Yalnızca fabrikada üretilen nesneler değil, kullanıcıların temel sınıfından diye bir yapıcı maruz olanları destekleyecek https://github.com/petli/node-addon-examples/commit/d3e92cd060a26da2623690718e78f9005db060a8

:

İşte yöntemini gösteren eklenti fabrika sınıfı demo için bir yama var. Bununla birlikte, bu prototip zincirinin yürümesiyle genelleştirilebilir.

Local<Object> obj = constructor->NewInstance(); 
prototype = Persistent<Value>::New(obj->GetPrototype()); 

Ve sonra nesneyi çözümleyecek önce kontrol eder: Özetle

, bu MyObject::Init beklenen sınıf prototip referans tutunuyor

MyObject* MyObject::CheckedUnWrap(Handle<Object> handle) 
{ 
    if (!handle.IsEmpty() && handle->InternalFieldCount() == 1) { 
    Handle<Value> objproto = handle->GetPrototype(); 
    if (objproto == prototype) { 
     // OK, this is us 
     return ObjectWrap::Unwrap<MyObject>(handle); 
    } 
    } 

    ThrowException(Exception::TypeError(String::New("<this> is not a MyObject"))); 
    return NULL; 
} 

Tüm fonksiyonlar daha sonra yerine CheckedUnWrap kullanmak : Ben als

Handle<Value> MyObject::PlusOne(const Arguments& args) { 
    HandleScope scope; 

    MyObject* obj = CheckedUnWrap(args.This()); 
    if (obj) { 
    obj->counter_ += 1; 
    return scope.Close(Number::New(obj->counter_)); 
    } 
    else { 
    // Invalid type, an exception has been thrown so return an empty value 
    return Handle<Value>(); 
    } 
} 

oldu o bir iç alan ekleyerek ve bazı sihirli işaretçilere göre ayarlamak, ancak daha sonra kod o iç alanların nasıl kullandığını değiştirmezdi node::ObjectWrap değişmeyecektir.

+0

Teşekkür

Persistent<Function> Wrapper::constructor; Persistent<FunctionTemplate> Wrapper::tpl; 

Sonra Wrapper::Init() işlevinde, kamu Kalıcı nesne ayarlayın. Bu problemi tekrar gözden geçiriyorum ve cevabınız daha önce kabul edilen cevaptan "daha iyi". Yani seninkini kabul etmek – BigONotation

3

Güncelleme: NanHasInstance kullanımdan kaldırıldı olduğundan, bu cevaba yeni çözüm bool FunctionTemplate::HasInstance(Local<Value> object) kullanmaktır. Belirtilen nesne bu işlev şablonunun bir örneği ise, bu işlev true değerini döndürür. unwrap Şimdi

Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New); 
// ... 
Wrapper::tpl.Reset(isolate, tpl); 

: Güncellenmiş yanıt için

Local<FunctionTemplate> wrapper_tpl = Wrapper::tpl.Get(isolate); 
if (!(wrapper_tpl->HasInstance(args[0]))) { 
    isolate->ThrowException(Exception::TypeError(
     String::NewFromUtf8(isolate, "Argument must be a Wrapper object"))); 
    return; 
} 
// Now we are safe to call ObjectWrap::Unwrap 
İlgili konular