2012-07-08 2 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 
    } 
} 

편집 :

에게 그것을 귀하의 자바 스크립트 함수는 하나의 인수 (두 값의 배열로 구성됨)를 기대하지만, 마치 우리가 func을 호출하는 것처럼 보입니다. 두 가지 주장.

이 가설을 테스트하려면, 당신이 그들을 두 개의 인수를 가지고 비교하기 위해 자바 스크립트 함수를 변경할 수 있습니다, 예를 들면 :

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를 사용하는 데 문제가 있습니다. 컴파일 타임에 (js_result.IsInt32)가 다음 오류를 제공하는 경우 오류가 발생합니다. '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