将std :: string转换为v8 :: string,反之亦然?

时间:2018-01-05 12:13:12

标签: c++ node.js string casting v8

我试图用c ++创建我的第一个节点模块。我只是想做一个简单的Hello传递我的名字作为参数。我发现这种方法可以将参数转换为v8 :: strings,这看起来很难看:

Get-Help

有没有人可以建议我做这种演员的简单方法?!我错过了什么吗?!

7 个答案:

答案 0 :(得分:3)

要转换为/ std::stringNewFromUtf8Utf8Value是合适的。但是,对于您的示例,来回转换不是必需的(事实上,效率非常低),您可以这样做:

Local<String> name = args[0]->ToString();

答案 1 :(得分:2)

好吧,我在使用节点12和v8 7.4.288时遇到了很多麻烦。

所有常用的东西都已弃用,因此我启动了gdb来检查实际情况。

所以-我假设首先您是从Argument中读取字符串的-明智的方式(我可以从文档和示例中找出的唯一方法而又不会太费力)是:

v8::Local<v8::String> fileName; 
fileName = args[0].As<v8::String>();

对-现在您有了v8格式的“字符串”(为v8::Local<v8::string>

要获取对v8 :: string的访问权限(因此,任何当前的v8 :: String东西甚至都稍微有用)-您需要像这样取消引用变量:

* fileName //现在是v8 :: String-您可以使用诸如WriteUtf8之类的功能-您可以使用的功能在此处进行了记录:

https://v8docs.nodesource.com/node-12.0/d2/db3/classv8_1_1_string.html

您会看到WriteUtf8函数需要隔离参数和一个char *缓冲区-我只是在这里猜测我的最大字符串长度,并创建一个快速的char缓冲区来保存我认为有意义的内容:

char* charFileName = new char[8192];

现在我有足够的空间来存储一些UTF 8字符串-我可以通过调用WriteUtf8函数来实现

(*fileName)->WriteUtf8(isolate, charFileName);

最后-我已经在其他地方(在全球范围内)定义了std :: string

static std::string stringFileName;

所以-要将char *中的数据获取到我的std :: string中,我这样做:

stringFileName.assign(charFileName);

如果愿意,还可以通过调用std :: string构造函数并将char *传递给构造函数来实现。

并且我删除了原来的char *以进行清理,因为它不再需要-std :: string超出范围时将在其自身之后进行清理-我不知道v8如何在其自身之后进行清理,老实说我不知道不在乎。

delete charFileName;

最后-v8 :: String字符串转换为可用的std :: string-今天(2020年)

此外-如果您现在想在std :: string和V8 :: String之间进行转换,您可能会做类似的事情-将std::string转换为char*,创建一个<v8::Local<v8::String>> ,将其(*mylocalv8string)取消引用,然后对该已取消引用的localv8string调用NewFromUtf8 (isolate, char*)

答案 2 :(得分:1)

我建议为此创建包装器。如果它不为空,您还必须检查本地句柄name。较新的实现使用MaybeLocal句柄来确保已检查任何结果。

我所做的一些例子:

/* Tool: JS execution has been terminated. */
class TerminateEx : public exception {
public:
    virtual const char* what() const throw()
    { return "JSBaseClass: Execution terminated"; };
};

/* Tool: Convert MaybeLocal<> to Local<>
 * Throws TerminateEx if the handle is empty (JS execution has been
 * terminated).
 */
template<typename C>
inline v8::Local<C>
JSBaseClass::toLocalHandle(v8::MaybeLocal<C> handle)
{
    if (handle.IsEmpty())
        throw TerminateEx();
    return handle.ToLocalChecked();
}

/* Tool: Create JS string*/
inline
v8::Local<v8::String>
JSBaseClass::newJSString(v8::Isolate *isolate, const char *str)
{
    return (toLocalHandle(
                v8::String::NewFromUtf8(
                    isolate, str, v8::NewStringType::kNormal)));
};

/* Tool: Create JS string*/
inline
v8::Local<v8::String>
JSBaseClass::newJSString(v8::Isolate *isolate, const string &str)
{
    return newJSString(isolate, str.c_str());
};

/* Tool: Create JS string*/
template<typename T>
inline v8::Local<v8::String>
JSBaseClass::newJSString(const T &info, const string &str)
{
    return newJSString(info.GetIsolate(), str.c_str());
};

[...]

/* Tool: Throw JS exception */
template<typename T> inline void
JSBaseClass::throwJSError(const T &info, const string &text)
{
    info.GetIsolate()->ThrowException(
        v8::Exception::Error(newJSString(info, text.c_str())));
    info.GetReturnValue().SetUndefined();
    return;
};

[...]

/* Tool: Get string from JS value. returns false if the conversion failed. */
inline bool
JSBaseClass::valueToString(
    const v8::Local<v8::Context> &context,
    const v8::Local<v8::Value> &value,
    string *str)
{
    v8::String::Utf8Value utf8Str(
        toLocalHandle(value->ToString(context)));
    if (!*utf8Str)
        return false;

    *str = *utf8Str;
    return true;
}

然后像这样使用它:

try {
    auto isolate = info.GetIsolate();
    auto context = isolate->GetCurrentContext();

    Local<Value> name = JSBaseClass::newJSString(info, "My Name");

    [...]

    string nameStr;

    if (!JSBaseClass::valueToString(context, name, &nameStr)) {
        JSBaseClass::throwJSError(info, "Not a string");
        return;
    }
    [...]
}
catch (JSBaseClass::TemplateEx) {
    return;
}

我使用较新版本的V8,应避免使用已弃用的方法。当前的方法主要返回MaybeLocal<>句柄。

答案 3 :(得分:1)

v8的较新版本也需要隔离:

void Foo(const v8::FunctionCallbackInfo<v8::Value> &args)
{
  // from v8 to cpp
  v8::Isolate* isolate = args.GetIsolate();
  v8::String::Utf8Value str(isolate, args[0]);
  std::string cppStr(*str);

  // back to v8
  v8::Local<v8::String> v8String = v8::String::NewFromUtf8(isolate, cppStr.c_str(), v8::String::kNormalString);
}

答案 4 :(得分:0)

你也可以尝试这种方法

    void StringConversion(const FunctionCallbackInfo<Value>& args){
        Isolate* isolate = args.GetIsolate(); // isolate will isolate the whole process in new memory space; so that no other thread can make change onto it at the same time 
        v8::String::Utf8Value s(args[0]); // take the string arg and convert it to v8::string
        std::string str(*s); // take the v8::string convert it to c++ class string
        //convert back the **str** to v8::String, so that we can set and return it 
        Local<String> result= String::NewFromUtf8(isolate,str.c_str()); // c_str() will return a pointer to an array that contain null-terminator sequence  
        args.GetReturnValue().Set(result);
    }

谢谢!

答案 5 :(得分:0)

节点> v13

这是我从char *类型转换为

的方式
cl

2020 中获取节点> v13 中的返回值:

v8::Local<v8::String>

答案 6 :(得分:0)

我了解了如何从std::String更改为v8::Local<String>,但是我试图做相反的事情,将Local<String>更改为std :: String。

更具体地说,可以使用以下命令将其输出到文件中:

  std::ofstream outfile("test.txt");
  outfile << source << std::endl;

谢谢!