使用 node.js 从 C++ 调用 JavaScript
Posted
技术标签:
【中文标题】使用 node.js 从 C++ 调用 JavaScript【英文标题】:Calling JavaScript from C++ with node.js 【发布时间】:2015-05-23 18:44:58 【问题描述】:有没有办法通过 node.js 从 C++ 调用 JS 函数(作为回调或类似的东西)? 如果是,如何? 我正在网上搜索它,但没有找到任何有用的资源。
提前致谢
【问题讨论】:
***.com/questions/9629677/… nodejs.org/api/addons.html#addons_callbacks 这些链接与 OP 所要求的完全相反。如何调用JS FROM C++. 【参考方案1】:当然可以。例如,如果你想在C++
中编写一个简单的阶乘函数,你可以这样做
#include <node.h>
using namespace v8;
int factorial(int n)
if (n == 0) return 1;
else return n * factorial(n - 1);
void Factorial(const FunctionCallbackInfo<Value>& args)
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
if (args.Length() != 2)
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
else
if (!(args[0]->IsNumber() && args[1]->IsFunction()))
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong arguments type")));
else
int result = factorial(args[0]->Int32Value());
Local<Function> callbackFunction = Local<Function>::Cast(args[1]);
const unsigned argc = 1;
Local<Value> argv[argc] = Number::New(isolate, result) ;
callbackFunction->Call(isolate->GetCurrentContext()->Global(), argc, argv);
void Init(Handle<Object> exports)
NODE_SET_METHOD(exports, "factorial", Factorial);
NODE_MODULE(Factorial, Init)
在你的 javascript
文件中,这样称呼它
var factorialAddon = require('./addons/Factorial');
factorialAddon.factorial(5, function (result)
console.log(result);
);
【讨论】:
他的意思是相反的......来自cpp调用js【参考方案2】:答案是肯定的,这里有一个方法:
我创建了一个名为 index.js 的 js 文件,这是文件的路径
D:\NodeJS\call_js_from_cpp
它包含以下代码
console.log("hello");
现在我有一个 C++ 代码,它执行以下 shell 命令并将输出存储在变量“输出”(它是一个字符串)中:
node D:\NodeJS\call_js_from_cpp\index.js
这里是C++代码:(注意在代码中,路径中有双\所以它变成了这个节点D:\NodeJS\call_js_from_cpp\index.js)
#include<iostream>
#include<fstream>
#include<string>
#include<cstdlib>
#include<sstream>
std::string ssystem (const char *command)
char tmpname [L_tmpnam];
std::tmpnam ( tmpname );
std::string scommand = command;
std::string cmd = scommand + " >> " + tmpname;
std::system(cmd.c_str());
std::ifstream file(tmpname, std::ios::in );
std::string result;
if (file)
while (!file.eof()) result.push_back(file.get());
file.close();
remove(tmpname);
return result;
//for cygwin
int main(int argc, char *argv[])
std::string bash = "node D:\\NodeJS\\call_js_from_cpp\\index.js";
std::string in;
std::string s = ssystem(bash.c_str());
std::istringstream iss(s);
std::string output;
while ( std::getline(iss, output) )
std::cout << output;
return 0;
【讨论】:
我认为 OP 是在询问是否引用了 v8 的函数并调用它,而不是从 C++ 应用程序生成节点进程。 @SigmaSoldier,您的意思是在 C++ 进程和 Nodejs 进程之间建立 IPC,C++ 将能够触发 NodeJs 的功能?或者您是否打算针对 NodeJs 进程使用 C++ 信号来触发这些功能?有很多方法可以根据要求“通过 node.js(作为回调或类似的东西)从 C++ 调用 JS 函数”,而这似乎是最简单和最直观的一种。 我认为 OP 意味着编写一个本地插件来捕获对函数的引用,然后调用它。但无论如何,这应该由 OP 澄清。【参考方案3】:形成原生插件的一种方法是使用提供的函数作为回调,例如,假设您在原生环境中声明了一个名为 setPrintFunction()
的函数(原生插件):
(例如打电话给main.cc
)
#include <node.h>
#include <string>
v8::Persistent<v8::Function> fn;
// Call this at any time, but after the capture!
void printToNode(std::string msg)
auto isolate = fn->GetIsolate();
// This part is the one that transforms your std::string to a javascript
// string, and passes it as the first argument:
const unsigned argc = 1;
auto argv[argc] =
v8::String::NewFromUtf8(isolate,
msg.c_str(),
v8::NewStringType::kNormal).ToLocalChecked()
;
cb->Call(context, Null(isolate), argc, argv).ToLocalChecked();
// This is your native function that captures the reference
void setPrintFunction(const v8::FunctionCallbackInfo<Value>& args)
auto isolate = args.GetIsolate();
auto context = isolate->GetCurrentContext();
auto cb = v8::Local<v8::Function>::Cast(args[0]);
fn = v8::Persistent<v8::Function>::New(cb);
// This part exports the function
void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module)
NODE_SET_METHOD(module, "exports", setPrintFunction);
NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
然后,只需导入您的插件并像这样使用它:
(例如打电话给index.js
)
const setPrintFunction = require('<your path to .node file>');
function printNodeMsg(msg)
console.log('<msg>: ' + msg);
setPrintFunction(printNodeMsg);
因此,您基本上要做的是捕获对v8::Function
的引用(这是javascript 函数,但在本机环境中),然后调用它并将"Hello World!"
作为第一个(也是唯一的)参数传递。
关于这个主题的更多信息:https://nodejs.org/api/addons.html
【讨论】:
您能否添加一个示例如何在 C++ 中使用该解决方案?在这种情况下,将std::string
传递给 C++ 函数,该函数将传递给对应的 Javascript。
我想我得到了你想要的:例如,可以是一个函数,它捕获对另一个函数的引用,然后根据你的意愿,在调用它的本机部分中创建一个函数。这可能是一个可能的解决方案?
好吧,当我问这个问题时,我想知道以下内容:假设我有一个 JS 函数printNodeMsg(msg)
,我想调用它并将msg
参数传递给它C++。插件不是问题,但我希望能够传递参数,而不仅仅是调用函数。所以基本上调用C++函数void printNodeMsg(const std::string& msg)
会在JS站点调用prontNodeMsg(msg)
,传递指定的字符串数据。
这个解决方案不是与OP的问题相反吗?
@barath OP 询问如何从 C++ 上下文调用 JavaScript 创建的函数,但使用 node.据我所知,OP 想要一个可以提供 JS 函数的 C/C++ 过程,以便可以从 JS 上下文中制作它,但稍后在 C++ 程序的过程中使用。以上是关于使用 node.js 从 C++ 调用 JavaScript的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用 Emscripten 从 JavaScript 调用 C++ 函数?
使用包含来自 Node.js 的 char 数组的结构调用 C++ dll