从v8函数中获取默认参数的最短路径(单线程)?

时间:2012-05-08 22:12:40

标签: c++ node.js v8 node.js-addon

自从我使用C ++以来已经有很长一段时间了,甚至更长时间以来我一直围绕着硬类型。我只是在寻找一个工作一个衬里来从v8获取一个参数,或者在没有提供一个参数时使用默认值。

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

4 个答案:

答案 0 :(得分: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");

    ...
}

答案 1 :(得分:3)

这段代码很适合我从一行中的v8值中提取字符串值:

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

std :: string构造函数应该处理您的默认方案而不需要额外的代码,但如果您确实需要手动检查空值,这是微不足道的。

这段代码作为一个例子,它获取所有参数的字符串值并将它们打印到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;
}

答案 2 :(得分:2)

Egorov是正确的,因为临时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!
...

这是因为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.

如果只打算使用一次字符串值,那么使用紧凑表示法仍然完全可以:

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

doSomethingWithString函数获取正确的值。只有从它返回,然后Utf8Value如果自动销毁。

String :: AsciiValue也是如此。

答案 3 :(得分:0)

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