2012-07-08 57 views
25

私はC++とv8で作業しており、次のような問題に取り組んでいます。v8を使用してjavascriptで関数を定義し、 C++。さらに、私はC++からjavascript関数に引数を渡すことができるようにしたい。私は、次のサンプルソースコードがそれを最もよく説明すると思います。サンプルコードの最後に向かってチェックして、私が達成しようとしていることを確認してください。引数を指定してC++からv8のjavascript関数を呼び出す

#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); 

} 

ヒントはありますか?

UPDATE:与えられたアドバイスに基づいて

、私は次のコードをまとめることができました。これは、テストされ、機能してきた:

#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がtrueを返すと仮定しますが、Int32Valueは0を返しますか? –

+0

私の編集をチェックしてください - おそらく十分なパラメータを渡していないかもしれません... –

+0

コードに間違いがあります:あなたは現在のコンテキストを破棄し、それを使用した後に処分します。あなたはプログラムの最後にdispose行を置く必要があります。 – banuj

答えて

13

私はこれをテストしていませんが、それはこのような何かが動作することが可能です:

// ...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 
    } 
} 

編集:

それは、あなたのjavascript関数は1つの引数(2つの値の配列で構成されています)を期待しているようですが、ちょうど私たちが渡してfunc 2つの議論で。この仮説を検証するために

、あなたは例えば、2つの引数を取り、それらを比較するために、あなたのjavascript機能を変更することができます:

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

それは働いているようです。私はjs_resultの使用に問題があります。エラー: 'class v8 :: Handle 'に 'Int32'という名前のメンバーがありません。 – user396404

+1

@ user396404:代わりに 'js_result-> IsInt32()'を試してみてください。 –

+0

それはうまくいった。コードはコンパイルされますが、値が一致しても値1が返されません。/ – user396404

2

次のようにもう一つの簡単な方法は次のとおりです。

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

基本的にいくつかのコードをコンパイルしますそれは無名関数を返し、それからあなたが渡したい引数でそれを呼び出します。

+0

v8 :: ScriptCompiler :: CompileFunctionInContextはあなたのために「関数内のコードをラップする」ビットです。 – xaxxon

関連する問題