2012-05-08 1 views
5

C++을 사용한 이후로 오랜 시간이 걸렸습니다. 단단한 유형에서 머리를 감 쌌기 때문에 오랜 시간이 걸렸습니다. 난 단순히 v8에서 인수를 얻으려면 하나의 라이너를 작동하거나 인수가 제공되지 않은 경우 기본값을 찾고 있어요.v8 함수에서 기본 인수를 얻는 가장 짧은 방법 (1 라이너)?

v8::String::Utf8Value arg0(args[0]); 
v8::String::Utf8Value arg1(args[1]); 
v8::String::Utf8Value arg2(args[2]); 
const char *username = (args.Length() > 0) ? *arg0 : ""; 
const char *password = (args.Length() > 1) ? *arg1 : ""; 
const char *service = (args.Length() > 2) ? *arg2 : "login"; 

출력 : 불행하게도

 
func(); // { username: "", password: "", service: "login" } 
func('1'); // { username: "1", password: "", service: "login" } 
func('1', '2'); // { username: "1", password: "2", service: "login" } 
func('a', 'b', 'c'); // { username: "a", password: "b", service: "c" } 

는 근접에 이상적인 솔루션 (어떤 아이디어 왜?) 나를 위해 작동하지 않습니다 다음 :

const char *username = (args.Length() > 0) ? *v8::String::Utf8Value(args[0]->ToString()) : ""; 
const char *password = (args.Length() > 1) ? *v8::String::Utf8Value(args[1]->ToString()) : ""; 
const char *service = (args.Length() > 2) ? *v8::String::Utf8Value(args[2]->ToString()) : "login"; 
+0

나는 v8에 대해 많이 모른다는 것을 인정하지만, C++ POV에서 당신의 대체물은 의심 스럽다. arg0/arg1/arg2의 소멸자는 언제 실행합니까? 그 소멸자는 언제 당신의 한줄기에서 달릴 수 있습니까? 클래스의 소멸자가 실행될 때 할당 된 메모리는 어떻게됩니까? – hvd

+0

하하하하 ... 하느님.그래서 afaik (v8의 모든 것들이 메모리 관리에 정적이고 끔찍한 것을 제외하고는 어디에서나 모든 것에 액세스해야하는 JS 엔진이기 때문에) : args *는 함수가 반환되면 파괴 될 수도 있지만 ... 가능합니다. 그 v8은 내부의 "스택 추적"을 위해 데이터에 매달린다. 기본적으로, 나는 명확하게 알지 못한다. 끝나면 코드를 프로파일 링 할 것이다. ;) –

+0

하나의 라이너가 정확히 "가장 깨끗한"솔루션은 아닙니다. –

답변

8

뱌체슬라프 에고 로프는 못을 박았다 그의 말과 함께 내가 현에 접근 할 무렵에는 그것이 파괴되었다.

char *get(v8::Local<v8::Value> value, const char *fallback = "") { 
    if (value->IsString()) { 
     v8::String::AsciiValue string(value); 
     char *str = (char *) malloc(string.length() + 1); 
     strcpy(str, *string); 
     return str; 
    } 
    char *str = (char *) malloc(strlen(fallback) + 1); 
    strcpy(str, fallback); 
    return str; 
} 

사용 예 : 궁극적으로 내가 사용하는 결국

v8::Handle<v8::Value> myMethod(const v8::Arguments &args) { 
    char *username = get(args[0], "user"); 
    char *password = get(args[1], "pass"); 

    ... 
} 
+2

P. 나는 내 자신보다 더 나은 대답을 받아 들일 것이다. 나는 정말로 내 자신의 질문에 답하는 것을 싫어한다. –

3

코드의이 비트는 한 줄의 V8 값에서 문자열 값을 추출하는 나를 위해 잘 작동 :

std::string tempString(*v8::String::Utf8Value(args[someInteger])); 

std :: string 생성자는 추가 코드가 필요없는 기본 시나리오를 처리해야하지만 null 값을 수동으로 확인해야하는 경우는 간단합니다.

이 코드는 모든 인수의 문자열 값을 가져 와서 표준 출력으로 출력하고, 물론 그들을 멋진 배열로 변환합니다. 왜냐하면 어떤 용도로 사용하고 있기 때문입니까? AsciiValue가 하나의 범위를 벗어난 간 때문이다

const char *username = *v8::String::Utf8Value(args[0]->ToString()); 
//transient AsciiValue object has gone out of scope, and its destructor has been called in 
// previous line, rendering the pointer (content) invalid henceforth! 
... 

:

std::string* printAllArgs(const Arguments& args){ 
    std::cout << "PRINTING ALL ARGS: "; 
    std::string* stringArray = new std::string[args.Length()]; 
    for(int i = 0; i < args.Length(); i++){ 
     std::string tempString(*v8::String::Utf8Value(args[i])); 
     stringArray[i] = tempString; 
     std::cout << tempString << ";"; 
    } 
    return stringArray; 
} 
2

에고 로프는 임시 AsciiValue 객체가 소형 표기법으로 스마트 포인터처럼 자동으로 파괴 된 올바른지 라인 범위. 한 번만 문자열 값을 사용하려는 경우

{ 
    v8::String::Utf8Value usernameObj(args[0]->ToString()); 
    const char *username = *usernameObj; 
    ... 
    //use username pointer as often as desired; it remains valid in this entire scope. 
    doSomethingWithString(username); //OK 

    //can also dereference Utf8Value object only when needed: 
    doSomethingWithString(*usernameObj); //OK 
} 
//here, usernameObj is out of scope and is destroyed, and username will become invalid. 

여전히 사용 무방하다 : 당신이 '캐시'포인터를 여러 번 사용하려는 경우 대신

, 2 개 라인으로 그것을 파괴한다 컴팩트 표기 :

doSomethingWithString(*v8::String::Utf8Value(args[0]->ToString())); //OK 

doSomethingWithString 기능이 작동 할 수있는 올바른 값을 가져옵니다. 그로부터 돌아 오는 경우에만 Utf8Value이 자동으로 파괴됩니다.

String :: AsciiValue도 마찬가지입니다.

0
string bi = info[0]->IsUndefined() ? "backwardIndex.dat" : string(*Nan::Utf8String(info[0]));