5

C++ を使用するのは久しぶりで、ハード型に頭を悩ませるのはさらに久しぶりです。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";

出力:

関数(); // { ユーザー名: ""、パスワード: ""、サービス: "ログイン" }
関数 ('1'); // { ユーザー名: "1"、パスワード: ""、サービス: "ログイン" }
func('1', '2'); // { ユーザー名: "1"、パスワード: "2"、サービス: "ログイン" }
func('a', 'b', 'c'); // { ユーザー名: "a"、パスワード: "b"、サービス: "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";
4

4 に答える 4

8

Vyacheslav Egorov は彼のコメントでそれを釘付けにしました。最終的に私は使用することになりました:

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

    ...
}
于 2012-05-09T21:42:29.577 に答える
3

このコードは、v8値から1行で文字列値を抽出するのにうまく機能しました。

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

std :: stringコンストラクターは、追加のコードを必要とせずにデフォルトのシナリオを処理する必要がありますが、null値を手動でチェックする必要がある場合、これは簡単です。

このコードは例として機能し、すべての引数の文字列値を取得してstdoutに出力します。もちろん、それらを出力するのはどのような用途なので、適切な配列に配置しますか?

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;
}
于 2012-06-19T18:45:11.653 に答える
2

AsciiValueEgorovは、一時オブジェクトがコンパクト表記のスマートポインターのように自動破棄されているという点で正しいです。

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!
...

これは、AsciiValueがその単一行スコープのスコープ外になっているためです。

代わりに、「キャッシュされた」ポインタを数回使用する場合は、2行に分割する必要があります。

{
  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.

文字列値を1回だけ使用する場合でも、コンパクトな表記を使用してもまったく問題ありません。

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

関数は、doSomethingWithString操作する正しい値を取得します。それから戻ったときだけ、それからUtf8Valueifは自動破壊されました。

String::AsciiValueでも同じことが起こります。

于 2013-03-12T07:05:56.987 に答える