2012-12-22 18 views
5

Google का v8 दस्तावेज वर्णन करता है कि जावास्क्रिप्ट संदर्भ में वैश्विक फ़ंक्शन कैसे जोड़ें। हम काफी आसानी से सी ++ 11 नए लैम्ब्डा सुविधा का उपयोग कर एक printf की तरह समारोह को लागू कर सकते हैं:v8 :: फ़ंक्शन टेम्पलेट एक गैर-वैश्विक परिवर्तनीय संदर्भित करता है

Handle<ObjectTemplate> global = ObjectTemplate::New(); 
global->Set(String::New("print"), FunctionTemplate::New(
[](const v8::Arguments &args) -> v8::Handle<v8::Value> 
{ 
    v8::String::AsciiValue ascii(args[0]); 
    std::cout << *ascii << "\n"; 
})); 
Persistent<Context> context = Context::New(NULL, global); 

यह किसी भी वैश्विक जावास्क्रिप्ट समारोह है कि या तो राज्यविहीन या संदर्भ एक वैश्विक सी ++ चर के लिए अच्छी तरह से काम (यानी std::cout) । लेकिन क्या होगा यदि हम चाहते हैं कि हमारा वैश्विक जावास्क्रिप्ट फ़ंक्शन गैर-वैश्विक C++ चर के संदर्भ में हो? उदाहरण के लिए, मान लें कि हम अपने स्वयं के वैश्विक print फ़ंक्शन के साथ कई अलग-अलग जावास्क्रिप्ट संदर्भ बना रहे हैं जो एक अलग C++ std::ostream का उपयोग करता है?

Persistent<Context> create_context(std::ostream &out) 
{ 
    Handle<ObjectTemplate> global = ObjectTemplate::New(); 
    global->Set(String::New("print"), FunctionTemplate::New(
    [&out](const v8::Arguments &args) -> v8::Handle<v8::Value> 
    { 
    v8::String::AsciiValue ascii(args[0]); 
    out << *ascii << "\n"; 
    })); 
    return Context::New(NULL, global); 
} 

दुर्भाग्य से, v8 इस समर्थन करने के लिए प्रतीत नहीं होता: v8 समारोह टेम्पलेट्स समारोह संकेत के बजाय std::function वस्तुओं का इस्तेमाल किया है, तो हम कुछ इस तरह करना होगा। मुझे लगता है (उम्मीद है?) कि v8 में कुछ कार्यात्मक रूप से समकक्ष करने का एक तरीका है, लेकिन मुझे खुद को v8::FunctionTemplate के लिए डॉक्सीजन द्वारा रहस्यमय पाया गया है। क्या कोई ऐसा व्यक्ति जिसने कुछ ऐसा करने का प्रयास किया है, तो प्रक्रिया को और अधिक समझा जा सकता है? मैं यह भी सीखना चाहूंगा कि एक जावास्क्रिप्ट ऑब्जेक्ट का वैश्विक उदाहरण कैसे बनाया जाए जो कि C++ ऑब्जेक्ट के मौजूदा, गैर-वैश्विक उदाहरण से जुड़ा हुआ है।

उत्तर

6

मेरे अपने प्रश्न के उत्तर में ... कुंजी यह जानना है कि v8 :: तर्क केवल तर्कों की एक सरणी नहीं है। इसमें अत्यधिक उपयोगी Callee() और Data() विधियां भी शामिल हैं। यदि फ़ंक्शन जावास्क्रिप्ट ऑब्जेक्ट का एक तरीका है तो Callee(), मुझे लगता है कि उस ऑब्जेक्ट के किसी भी उदाहरण को पकड़ने के लिए इस्तेमाल किया जा सकता है जिस पर विधि को बुलाया गया था। तब उपयोगी राज्य जानकारी ऑब्जेक्ट इंस्टेंस में संग्रहीत की जा सकती है। किसी ऑब्जेक्ट में फ़ंक्शन टेम्पलेट जोड़ते समय, आप डेटा हैंडल भी प्रदान कर सकते हैं, जो किसी भी C++ ऑब्जेक्ट को void* के माध्यम से इंगित कर सकता है। इस फ़ंक्शन-विशिष्ट डेटा हैंडल को Data() विधि के माध्यम से एक्सेस किया जा सकता है।

नीचे v8::Arguments::Data() का उपयोग कर प्रश्न में क्या करने का प्रयास कर रहा था इसका एक पूर्ण उदाहरण है। उम्मीद है कि यह किसी के लिए उपयोगी होगा जो कुछ ऐसा करना चाहता है। यदि आपके पास एक वैकल्पिक रणनीति है जो आपको पसंद है (और मुझे यकीन है कि ऐसा करने के एक से अधिक तरीके हैं), तो कृपया इसे किसी अन्य उत्तर में जोड़ने के लिए स्वतंत्र महसूस करें!

#include <iostream> 
#include <ostream> 
#include <v8.h> 

// add print() function to an object template 
void add_print(v8::Handle<v8::ObjectTemplate>& ot, std::ostream* out) 
{ 
    // add function template to ot 
    ot->Set(v8::String::New("print"), v8::FunctionTemplate::New(
    // parameter 1 is the function callback (implemented here as a lambda) 
    [](const v8::Arguments& args)->v8::Handle<v8::Value> 
    { 
     // recover our pointer to an std::ostream from the 
     // function template's data handle 
     v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(args.Data()); 
     std::ostream* out = static_cast<std::ostream*>(data->Value()); 

     // verify that we have the correct number of function arguments 
     if (args.Length() != 1) 
     return v8::ThrowException(v8::String::New("Too many arguments to print().")); 

     // print the ascii representation of the argument to the output stream 
     v8::String::AsciiValue ascii(args[0]); 
     *out << *ascii << "\n"; 

     // like 'return void;' only in JavaScript 
     return v8::Undefined(); 
    }, 

    // parameter 2 is the data handle with the pointer to an std::ostream 
    v8::External::New(out) 
)); 
} 

int main() 
{ 
    // create a stack-allocated handle scope 
    v8::HandleScope handle_scope; 

    // create a global template 
    v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); 

    // add a print() function using std::cout to the global template 
    add_print(global, &std::cout); 

    // create a context 
    v8::Persistent<v8::Context> context = v8::Context::New(nullptr, global); 

    // enter the created context 
    v8::Context::Scope context_scope(context); 

    // create a string containing the JavaScript source code 
    v8::Local<v8::String> source = v8::String::New("print('1 + 1 = ' + (1 + 1));"); 

    // compile the source code 
    v8::Local<v8::Script> script = v8::Script::Compile(source); 

    // run the script 
    script->Run(); 

    // dispose of the persistent context 
    context.Dispose(); 

    return 0; 
} 
संबंधित मुद्दे