2012-05-08 30 views
5

Đã lâu rồi kể từ khi tôi sử dụng C++, và thậm chí còn lâu hơn kể từ khi tôi quấn quanh đầu các loại cứng. Tôi chỉ đơn giản là tìm kiếm một làm việc một lớp lót để thực hiện một đối số từ v8 hoặc một giá trị mặc định khi đối số không được cung cấp.Cách ngắn nhất (một lớp lót) để lấy đối số mặc định từ một hàm 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"; 

Đầu ra:

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

Thật không may, sau đây close-to-lý tưởng giải pháp không làm việc cho tôi (bất kỳ ý tưởng tại sao?):

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

Tôi thừa nhận rằng tôi không biết nhiều về v8, nhưng thay thế của bạn trông mạnh mẽ đáng ngờ từ POV C++ đối với tôi: khi nào các trình phá hủy arg0/arg1/arg2 chạy? Khi nào những kẻ phá hủy đó chạy trong một lớp lót của bạn? Điều gì sẽ xảy ra với bộ nhớ được cấp phát khi destructor của lớp được chạy? – hvd

+0

Hah, ôi Chúa ơi ...afaik (ngoài thực tế là mọi thứ trong v8 là tĩnh và khủng khiếp đối với việc quản lý bộ nhớ vì nó là một công cụ JS cần truy cập mọi thứ ở khắp mọi nơi): args * có thể * bị hủy khi chức năng của tôi trả về ... nhưng .. rất có thể rằng v8 treo trên các dữ liệu cho nội bộ của nó "ngăn xếp truy tìm". Về cơ bản, tôi không biết tích cực, tôi chắc chắn sẽ lược tả mã khi nó kết thúc. ;) –

+0

Một lớp lót không phức tạp không chính xác là giải pháp "sạch" nhất. –

Trả lời

8

Vyacheslav Egorov đóng đinh nó với bình luận của anh ấy, vào lúc tôi truy cập vào chuỗi, nó đã bị phá hủy. Cuối cùng tôi đã kết thúc bằng:

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

Cách sử dụng Ví dụ:

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

    ... 
} 
+2

P.S. Tôi sẽ chấp nhận một câu trả lời tốt hơn của riêng tôi. Tôi thực sự ghét trả lời các câu hỏi của riêng tôi. –

3

chút mã này làm việc tốt cho tôi để trích xuất một chuỗi giá trị từ một giá trị v8 trong một dòng:

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

Trình tạo chuỗi std :: string nên xử lý các kịch bản mặc định của bạn mà không cần mã bổ sung, nhưng nếu bạn cần kiểm tra giá trị null theo cách thủ công, thì điều này là tầm thường.

Mã này phục vụ như một ví dụ, nó nhận các giá trị chuỗi của tất cả các đối số và in chúng thành tiêu chuẩn, và tất nhiên đặt chúng vào một mảng đẹp, bởi vì những gì sử dụng là in chúng ra?

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

Egorov là đúng ở chỗ đối tượng tạm thời AsciiValue đã được tự động bị phá hủy như một con trỏ thông minh trong các ký hiệu nhỏ gọn:

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

Điều này là do AsciiValue đã đi ra khỏi phạm vi ở chỗ đơn phạm vi-line.

Thay vào đó, nên chia nó ra thành 2 dòng nếu bạn có ý định sử dụng 'cache' con trỏ nhiều lần:

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

Nếu chỉ có ý định sử dụng các chuỗi giá trị một lần, nó vẫn hoàn toàn OK để sử dụng ký hiệu nhỏ gọn:

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

Chức năng doSomethingWithString nhận giá trị phù hợp để làm việc. Chỉ khi trở về từ nó, sau đó là Utf8Value nếu tự động bị hủy.

Điều tương tự cũng xảy ra đối với Chuỗi :: AsciiValue.

0
string bi = info[0]->IsUndefined() ? "backwardIndex.dat" : string(*Nan::Utf8String(info[0])); 
Các vấn đề liên quan