如何使用来自 C++ 插件的 node.js 内置模块
How to use node.js built in modules from C++ addons
我需要使用我的 C++ 插件中的 node.js 内置模块 'crypto'。
我试图找到使用内置模块的 C++ 插件示例,但失败了。
我查看了 node_crypto.h/.cc,与 node.js 加密文档、受保护的构造函数等相比,它具有如此不同的函数签名。node_crypto.h 包含带有一个参数的 InitCrypto() 声明,但是 node_crypto.cc 没有定义这样的函数。只有 InitCrypto 有四个参数。无论如何,我尝试使用带有一个参数的 InitCrypto 并得到 "symbol lookup error".
我可以将 require('crypto') 的结果传递给我的插件,然后使用这个对象,但这太不安全了。我们的 JS 代码在客户端的服务器上工作。
目前我认为 C++ 插件更简单地使用像 openssl lib 这样的 smth 而不是内置节点模块 'crypto'。
所以我需要一些使用 'crypto' 模块或 link 的 C++ 插件的工作示例。
任何使用 C++ 插件内置模块的示例都会有所帮助。
当需要 encrypt/decrypt Nodejs 插件中的数据时,我使用了相同的方法。
据我了解,node_crypto.h
中的 类 用于在 Nodejs 中进行本机绑定,我无法在我的插件中使用它们。
然后我尝试使用 Nodejs 中的 OpenSSL 但无法使用,因为 OpenSSL 静态链接到 Nodejs 可执行文件中。
之后我尝试从 C++ 调用 JavaScript 代码,最后得到以下解决方案 - 从 C++ 代码调用 Nodejs 函数:
using namespace v8;
// persistent handle for the crypto module
static Persistent<Object> node_crypto;
// Addon startup procedure
void Init(Local<Object> exports, Local<Object> module)
{
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
// get `require` function
Local<Function> require = module->Get(String::NewFromUtf8(isolate, "require")).As<Function>();
// call require('crypto')
Local<Value> args[] = { String::NewFromUtf8(isolate, "crypto") };
Local<Object> crypto = require->Call(module, 1, args).As<Object>();
// store crypto module in persistent handle for further use
node_crypto.Reset(isolate, crypto);
}
NODE_MODULE(addon, Init);
// must be invoked in then Node main thread since the function uses V8 API
std::string encrypt(std::string const& key, std::string const& text)
{
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
// get local handle from persistent
Local<Object> crypto = Local<Object>::New(isolate, node_crypto);
// get `createCipher` function from the crypto module
Local<Function> createCipher = crypto->Get(String::NewFromUtf8(isolate, "createCipher")).As<Function>();
// call crypto.createCipher("aes256", key)
Local<Value> create_args[] =
{
String::NewFromUtf8(isolate, "aes256"),
String::NewFromUtf8(isolate, key.c_str())
};
Local<Object> cipher = createCipher->Call(crypto, 2, create_args).As<Object>();
// get update and final functions from the crypto module
Local<Function> update = cipher->Get(String::NewFromUtf8(isolate, "update")).As<Function>();
Local<Function> final = cipher->Get(String::NewFromUtf8(isolate, "final")).As<Function>();
// buf1 = cipher.update(text), buf2 = cipher.final()
Local<Value> update_args[] = { node::Buffer::New(isolate, text.data(), text.size()) };
Local<Value> buf1 = update->Call(cipher, 1, update_args);
Local<Value> buf2 = final->Call(cipher, 0, nullptr);
// concatenate update and final buffers into result string
char const* const data1 = node::Buffer::Data(buf1);
char const* const data2 = node::Buffer::Data(buf2);
size_t const size1 = node::Buffer::Length(buf1);
size_t const size2 = node::Buffer::Lenght(buf2);
std::string result;
result.reserve(size1 + size2);
result.append(data1, size1);
result.append(data2, size2);
return result;
}
std::string decrypt(std::string const& key, std::string const& text)
{
// similar as in encrypt, use createDecipher instead
}
如您所见,使用 V8 API 的 C++ 代码非常冗长。在实际项目中,我使用 v8pp 库中的实用函数来获取对象属性并调用函数,并将数据转换为 V8 句柄。
我需要使用我的 C++ 插件中的 node.js 内置模块 'crypto'。 我试图找到使用内置模块的 C++ 插件示例,但失败了。 我查看了 node_crypto.h/.cc,与 node.js 加密文档、受保护的构造函数等相比,它具有如此不同的函数签名。node_crypto.h 包含带有一个参数的 InitCrypto() 声明,但是 node_crypto.cc 没有定义这样的函数。只有 InitCrypto 有四个参数。无论如何,我尝试使用带有一个参数的 InitCrypto 并得到 "symbol lookup error".
我可以将 require('crypto') 的结果传递给我的插件,然后使用这个对象,但这太不安全了。我们的 JS 代码在客户端的服务器上工作。
目前我认为 C++ 插件更简单地使用像 openssl lib 这样的 smth 而不是内置节点模块 'crypto'。
所以我需要一些使用 'crypto' 模块或 link 的 C++ 插件的工作示例。
任何使用 C++ 插件内置模块的示例都会有所帮助。
当需要 encrypt/decrypt Nodejs 插件中的数据时,我使用了相同的方法。
据我了解,node_crypto.h
中的 类 用于在 Nodejs 中进行本机绑定,我无法在我的插件中使用它们。
然后我尝试使用 Nodejs 中的 OpenSSL 但无法使用,因为 OpenSSL 静态链接到 Nodejs 可执行文件中。
之后我尝试从 C++ 调用 JavaScript 代码,最后得到以下解决方案 - 从 C++ 代码调用 Nodejs 函数:
using namespace v8;
// persistent handle for the crypto module
static Persistent<Object> node_crypto;
// Addon startup procedure
void Init(Local<Object> exports, Local<Object> module)
{
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
// get `require` function
Local<Function> require = module->Get(String::NewFromUtf8(isolate, "require")).As<Function>();
// call require('crypto')
Local<Value> args[] = { String::NewFromUtf8(isolate, "crypto") };
Local<Object> crypto = require->Call(module, 1, args).As<Object>();
// store crypto module in persistent handle for further use
node_crypto.Reset(isolate, crypto);
}
NODE_MODULE(addon, Init);
// must be invoked in then Node main thread since the function uses V8 API
std::string encrypt(std::string const& key, std::string const& text)
{
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
// get local handle from persistent
Local<Object> crypto = Local<Object>::New(isolate, node_crypto);
// get `createCipher` function from the crypto module
Local<Function> createCipher = crypto->Get(String::NewFromUtf8(isolate, "createCipher")).As<Function>();
// call crypto.createCipher("aes256", key)
Local<Value> create_args[] =
{
String::NewFromUtf8(isolate, "aes256"),
String::NewFromUtf8(isolate, key.c_str())
};
Local<Object> cipher = createCipher->Call(crypto, 2, create_args).As<Object>();
// get update and final functions from the crypto module
Local<Function> update = cipher->Get(String::NewFromUtf8(isolate, "update")).As<Function>();
Local<Function> final = cipher->Get(String::NewFromUtf8(isolate, "final")).As<Function>();
// buf1 = cipher.update(text), buf2 = cipher.final()
Local<Value> update_args[] = { node::Buffer::New(isolate, text.data(), text.size()) };
Local<Value> buf1 = update->Call(cipher, 1, update_args);
Local<Value> buf2 = final->Call(cipher, 0, nullptr);
// concatenate update and final buffers into result string
char const* const data1 = node::Buffer::Data(buf1);
char const* const data2 = node::Buffer::Data(buf2);
size_t const size1 = node::Buffer::Length(buf1);
size_t const size2 = node::Buffer::Lenght(buf2);
std::string result;
result.reserve(size1 + size2);
result.append(data1, size1);
result.append(data2, size2);
return result;
}
std::string decrypt(std::string const& key, std::string const& text)
{
// similar as in encrypt, use createDecipher instead
}
如您所见,使用 V8 API 的 C++ 代码非常冗长。在实际项目中,我使用 v8pp 库中的实用函数来获取对象属性并调用函数,并将数据转换为 V8 句柄。