我试图用c ++创建我的第一个节点模块。我只是想做一个简单的Hello传递我的名字作为参数。我发现这种方法可以将参数转换为v8 :: strings,这看起来很难看:
Get-Help
有没有人可以建议我做这种演员的简单方法?!我错过了什么吗?!
答案 0 :(得分:3)
要转换为/ std::string
,NewFromUtf8
和Utf8Value
是合适的。但是,对于您的示例,来回转换不是必需的(事实上,效率非常低),您可以这样做:
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)
这是我从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;
谢谢!