2012-01-24 7 views
8

मेरे पास 212 + कक्षाएं जावास्क्रिप्ट कक्षाओं, VanillaOption और NoomraEngine के रूप में उजागर हैं, दोनों ObjectWrap से विरासत में हैं।ऑब्जेक्टवाप को कॉल करते समय सही प्रकार की जांच कैसे करें :: नोडज एड-ऑन में अनवर्रप करें?

NoomraEngine में निम्न विधि में, मैं प्राप्त करने की अपेक्षा की हूँ पूर्व में "लिपटे" 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); 
} 

सब कुछ ठीक काम करता है, सिवाय इसके कि अगर मैं विधि के गलत प्रकार गुजरती हैं, ObjectWrap::Unwrap में नोड दुर्घटनाओं।

मेरा प्रश्न यह है कि मैं कैसे सुनिश्चित कर सकता हूं कि मुझे args[0] में सही प्रकार प्राप्त हुआ है?

उत्तर

3

संपादित करें: नीचे नंगे वी 8 एक से एक बेहतर तरीका NanHasInstance (https://github.com/rvagg/nan#api_nan_has_instance)

उपयोग करने के लिए MyObject::Init में है:

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

जहां prototype एक स्थिर है Persistent<FunctionTemplate>MyObject के सदस्य। इस तरह

उपयोग:

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

चेतावनी है कि यह एक नोड ऐड-ऑन लेखन में मेरी पहली जाने है साथ

, मैं चारों ओर मेरे अपने आवरण के साथ वस्तु के प्रोटोटाइप की जाँच करके इस सटीक समस्या हल UnWraphttps://github.com/petli/node-addon-examples/commit/d3e92cd060a26da2623690718e78f9005db060a8

यह केवल कारखाने में उत्पन्न वस्तुओं, और नहीं, जहां एक निर्माता सामने आ रहा है, ताकि उपयोगकर्ताओं को आधार वर्ग से विरासत सकता है लोगों का समर्थन करेंगे:

यहाँ विधि दिखा ऐड-ऑन कारखाने वर्ग डेमो के लिए एक पैच है। हालांकि, प्रोटोटाइप श्रृंखला चलकर इसे सामान्यीकृत किया जा सकता है।

सारांश में, यह MyObject::Init में उम्मीद वर्ग प्रोटोटाइप के संदर्भ में की पकड़ पकड़ लेता:

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

और फिर जाँच करता है कि वस्तु अपसंदर्भन से पहले:

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; 
} 

सभी कार्यों तो बजाय CheckedUnWrap का उपयोग :

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>(); 
    } 
} 

मैं अल था o एक आंतरिक क्षेत्र जोड़ने पर विचार करें और कुछ जादू सूचक को सेट करें, लेकिन तब कोड node::ObjectWrap पर निर्भर करेगा कि यह आंतरिक क्षेत्रों का उपयोग कैसे करेगा।

+0

अपने अपडेट किए गए जवाब के लिए धन्यवाद

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

फिर अपने Wrapper::Init() समारोह में, जनता लगातार वस्तु निर्धारित किया है। मैं इस समस्या का पुनरीक्षण कर रहा हूं और यह पता चला है कि आपका उत्तर पहले स्वीकृत उत्तर से "बेहतर" है। तो तुम्हारा स्वीकार कर रहा हूँ – BigONotation

3

अद्यतन: चूंकि NanHasInstance पदावनत किया गया है, इस सवाल का जवाब करने के लिए नए समाधान bool FunctionTemplate::HasInstance(Local<Value> object) उपयोग करने के लिए है। यह फ़ंक्शन सत्य लौटाता है यदि दिया गया ऑब्जेक्ट इस फ़ंक्शन टेम्पलेट का उदाहरण है। खोलने में

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

अब:

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 
संबंधित मुद्दे