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

问题描述 投票:0回答:6

我正在尝试用 C++ 创建我的第一个节点模块。我只想做一个简单的 Hello,将我的名字作为参数传递。我发现这种方法将参数转换为 v8::strings ,这看起来很丑陋:

Local<String> name = String::NewFromUtf8(isolate, *v8::String::Utf8Value(args[0]->ToString()));

有谁可以建议我简单的方法来进行这种演员阵容吗?!我是不是错过了什么?!

c++ node.js string casting v8
6个回答
6
投票

较新版本的 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);
}

3
投票

对于

std::string
的转换,
NewFromUtf8
Utf8Value
是合适的。然而,对于您的示例,来回转换是不必要的(事实上,效率很低),您可以简单地执行以下操作:

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

3
投票

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

所有常用的东西都已被弃用,所以我启动了 gdb 来检查实际现状。

所以 - 我假设你首先从参数中读取字符串 - 一种明智的方法(我可以从文档和示例中找出没有太多痛苦的唯一方法)是这样的:

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-20.3/d2/db3/classv8_1_1_string.html

您会看到

WriteUtf8
函数需要隔离参数和
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)
并调用
NewFromUtf8 (isolate, char*) 
在取消引用的 localv8string 上。


2
投票

节点 > v13

这是我如何从 char* 类型转换为类型

v8::Local<v8::String>

2020 对于节点 > v13 中的返回值:

v8::Isolate *isolate = info.GetIsolate();
auto context = isolate->GetCurrentContext();
v8::Local<v8::String> result; 
v8::MaybeLocal<v8::String> temp = String::NewFromUtf8(isolate, jsonOutput);
temp.ToLocal(&result); 
args.GetReturnValue().Set(result);

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<>
句柄。


1
投票

你也可以尝试这个方法

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

谢谢!!

© www.soinside.com 2019 - 2024. All rights reserved.