2012-07-08 19 views
25

Ben C++ ve v8 ile çalışıyorum ve aşağıdaki soruna cevap verdim: v8 kullanarak javascript'te bir işlevi tanımlayabilmek istiyorum, daha sonra işlevi C++. Ayrıca, javascript işlevine bir argümanını C++ 'dan geçirebilmek istiyorum. Aşağıdaki örnek kaynak kodunun en iyi şekilde açıklayacağını düşünüyorum. Neyi başarmaya çalıştığımı görmek için örnek kodun sonuna doğru işaretleyin.C++ 'dan v8 javascript işlevinin bir argüman ile çağrılması

#include <v8.h> 
#include <iostream> 
#include <string> 
#include <array> 

using namespace v8; 

int main(int argc, char* argv[]) { 

    // Create a stack-allocated handle scope. 
    HandleScope handle_scope; 

    // Create a new context. 
    Persistent<Context> context = Context::New(); 
    Context::Scope context_scope(context); 
    Handle<String> source; 
    Handle<Script> script; 
    Handle<Value> result; 

    // Create a string containing the JavaScript source code. 
    source = String::New("function test_function(test_arg) { var match = 0;if(test_arg[0] == test_arg[1]) { match = 1; }"); 

    // Compile the source code. 
    script = Script::Compile(source); 

    // What I want to be able to do (this part isn't valid code.. 
    // it just represents what I would like to do. 
    // An array is defined in c++ called pass_arg, 
    // then passed to the javascript function test_function() as an argument 
    std::array< std::string, 2 > pass_arg = {"value1", "value2"}; 
    int result = script->callFunction("test_function", pass_arg); 

} 

Herhangi bir ipucu?

GÜNCELLEME: Verilen tavsiye dayanarak

, birlikte aşağıdaki kodu koymak mümkün olmuştur. Bu test edilmiş ve çalışır edilmiştir: Bu test değil

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

using namespace v8; 

int main(int argc, char* argv[]) { 

// Create a stack-allocated handle scope. 
HandleScope handle_scope; 

// Create a new context. 
Persistent<Context> context = Context::New(); 

//context->AllowCodeGenerationFromStrings(true); 

// Enter the created context for compiling and 
// running the hello world script. 
Context::Scope context_scope(context); 
Handle<String> source; 
Handle<Script> script; 
Handle<Value> result; 


// Create a string containing the JavaScript source code. 
source = String::New("function test_function() { var match = 0;if(arguments[0] == arguments[1]) { match = 1; } return match; }"); 

// Compile the source code. 
script = Script::Compile(source); 

// Run the script to get the result. 
result = script->Run(); 
// Dispose the persistent context. 
context.Dispose(); 

// Convert the result to an ASCII string and print it. 
//String::AsciiValue ascii(result); 
//printf("%s\n", *ascii); 

Handle<v8::Object> global = context->Global(); 
Handle<v8::Value> value = global->Get(String::New("test_function")); 
Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); 
Handle<Value> args[2]; 
Handle<Value> js_result; 
int final_result; 

args[0] = v8::String::New("1"); 
args[1] = v8::String::New("1"); 

js_result = func->Call(global, 2, args); 
String::AsciiValue ascii(js_result); 

final_result = atoi(*ascii); 

if(final_result == 1) { 

    std::cout << "Matched\n"; 

} else { 

    std::cout << "NOT Matched\n"; 

} 

return 0; 

} 
+0

IsInt32'nin true döndürdüğünü varsayalım, ancak Int32Value 0 değerini döndürüyor mu? –

+0

Düzenlememize bir göz atın - belki de yeterli parametreleri geçmiyoruz ... –

+0

Kodunuzda bir hata var: mevcut içeriği ve onu kullandıktan sonra atın. Atma çizgisini programınızın sonuna koymalısınız. – banuj

cevap

13

, ancak böyle bir şey çalışacak mümkündür:

// ...define and compile "test_function" 

Handle<v8::Object> global = context->Global(); 
Handle<v8::Value> value = global->Get(String::New("test_function")); 

if (value->IsFunction()) { 
    Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); 
    Handle<Value> args[2]; 
    args[0] = v8::String::New("value1"); 
    args[1] = v8::String::New("value2"); 

    Handle<Value> js_result = func->Call(global, 2, args); 

    if (js_result->IsInt32()) { 
     int32_t result = js_result->ToInt32().Value(); 
     // do something with the result 
    } 
} 

Düzenleme:

It javascript işlevinizin tek bir argüman (iki değerden oluşan bir diziden oluşur) beklediğine benziyor, ancak bu, func'u arayarak iki argümanda.

Bu hipotezi test etmek, bunları iki argüman alır ve karşılaştırmak için JavaScript fonksiyonunu değiştirebilir, örneğin:

function test_function(test_arg1, test_arg2) { 
    var match = 0; 
    if (test_arg1 == test_arg2) { 
    match = 1; 
    } else { 
    match = 0; 
    } 
    return match; 
} 
+0

Çalışıyor gibi görünüyor. Yine de js_result kullanarak sorun yaşıyorum. Derleme zamanında (js_result.IsInt32) aşağıdaki hatayı verirse yazdığı kısım: error: v class v8 :: Handle ’adında hiç üye yok‘ Int32 ’| – user396404

+1

@ user396404: Belki js_result-> IsInt32() 'yerine deneyin? –

+0

Bu işe yaradı. Kod derler, ancak değerler eşleşse bile 1 değerini döndürmez:/ – user396404

2

başka daha basit bir yöntem aşağıdaki gibidir:

Handle<String> code = String::New(
    "(function(arg) {\n\ 
    console.log(arg);\n\ 
    })"); 
Handle<Value> result = Script::Compile(code)->Run(); 
Handle<Function> function = Handle<Function>::Cast(result); 

Local<Value> args[] = { String::New("testing!") }; 
func->Call(Context::GetCurrent()->Global(), 1, args); 

Esasen bazı kod derlemek Bu, anonim bir işlev döndürür, sonra bunu geçmek istediğiniz argümanlarla adlandırın.

+0

v8 :: ScriptCompiler :: CompileFunctionInContext, "kodunuzu bir işlevde sarmala" yapar. – xaxxon

İlgili konular