如何从javascript调用c++方法
How to call a C++ method from javascript
我有一个c++方法(该角色正在杀死一些进程)。她需要2个参数:a hostname and a port
。
另一方面,我正在开发一个web应用程序(使用Nodejs和AngularJS),运行在谷歌浏览器。
当我通过浏览器单击按钮时,我希望能够通过我的app.js
文件调用c++函数。
我还没有找到如何"绑定"javascript与c++。
编辑:我认为这个链接可能非常有用如何从node.js中使用c++库?您可以使用Google's V8
。V8
是Google的开源JavaScript
引擎。V8
可以运行standalone
,也可以将embedded
运行到任何C++
应用程序中。
下面来自github的示例演示了如何将C++
类绑定到Google V8
。v8_wrap_class.cpp -作者是nicholas
/*
* v8_wrap_class.cpp
*
* Created on: 14/01/2013
* Author: nicholas
* License: public domain
*/
#include <v8.h>
#include <cstdio>
#include <string>
#include <stdexcept>
#include <memory>
using namespace v8;
/*
var Simple = function(v)
{
this.value = v;
}
Simple.prototype.func = function()
{
alert(this.value);
}
var obj = new Simple(4);
obj.func();
*/
struct Simple
{
double value;
Simple(double v)
: value(v)
{
fprintf(stderr, "Simple::ctor'n");
}
void func()
{
fprintf(stderr, "Simple::func(%f)'n", value);
}
~Simple()
{
fprintf(stderr, "Simple::dtor'n");
}
};
namespace js
{
/*
* Retrieve the c++ object pointer from the js object
*/
template <typename T>
T* unwrap(const Arguments& args)
{
auto self = args.Holder();
auto wrap = Local<External>::Cast(self->GetInternalField(0));
return static_cast<T*>(wrap->Value());
}
/*
* Construct a new c++ object and wrap it in a js object
*/
template <typename T, typename... Args>
Persistent<Object> make_object(Handle<Object> object, Args&&... args)
{
auto x = new T(std::forward<Args>(args)...);
auto obj = Persistent<Object>::New(object);
obj->SetInternalField(0, External::New(x));
obj.MakeWeak(x, [](Persistent<Value> obj, void* data)
{
auto x = static_cast<T*>(data);
delete x;
obj.Dispose();
obj.Clear();
});
return obj;
}
}
void bind_Simple(Local<Object> global)
{
// Name the class in js
auto name = String::NewSymbol("Simple");
auto tpl = FunctionTemplate::New([&](const Arguments& args) -> Handle<Value>
{
if (!args.IsConstructCall())
return ThrowException(String::New("Cannot call constructor as function"));
HandleScope scope;
// Read and pass constructor arguments
js::make_object<Simple>(args.This(), args[0]->NumberValue());
return args.This();
});
tpl->SetClassName(name);
tpl->InstanceTemplate()->SetInternalFieldCount(1);
auto prototype = tpl->PrototypeTemplate();
// Add object properties to the prototype
// Methods, Properties, etc.
prototype->Set(String::New("func"), FunctionTemplate::New([](const Arguments& args) -> Handle<Value>
{
auto s = js::unwrap<Simple>(args);
s->func();
return {};
})->GetFunction());
auto constructor = Persistent<Function>::New(tpl->GetFunction());
global->Set(name, constructor);
}
int main()
{
std::string js_source = R"(
for(var i = 0; i < 1000; ++i)
{
var s = new Simple(4);
s.value = 5;
s.func();
}
)";
/*
* This code is mostly uninteresting.
* Just run the vm with the script provided.
*/
{
HandleScope handle_scope;
Handle<ObjectTemplate> global_template = ObjectTemplate::New();
Persistent<Context> context = Context::New(0, global_template);
Context::Scope context_scope(context);
auto global = context->Global();
// Wrap the class and bind to the global scope.
bind_Simple(global);
{
HandleScope handle_scope;
TryCatch trycatch;
Local<String> source = String::New(js_source.c_str(), js_source.size());
Local<Script> script = Script::Compile(source);
if (script.IsEmpty())
{
Handle<Value> exception = trycatch.Exception();
String::AsciiValue exception_str(exception);
throw std::runtime_error(*exception_str);
}
Local<Value> result = script->Run();
if (result.IsEmpty())
{
Local<Value> exception = trycatch.Exception();
String::AsciiValue exception_str(exception);
throw std::runtime_error(*exception_str);
}
}
context.Dispose();
context.Clear();
}
// Run the GC until there is nothing to reclaim.
while (!V8::IdleNotification())
;
return 0;
}
这个答案给出了在JavaScript中使用c++的四种方法。所示的方法尽量保持原来的c++标准和简单的c++实现。
用WASM的两种方法和SWIG和JRPC的两种方法给出了在JavaScript中执行c++的例子和思路。详细地说,这个答案给出了一个在浏览器中执行的例子和一个在使用WASM的NodeJS中执行的例子。这个答案的最后还列出了在JavaScript中执行c++的另外两种方法,其中一种是从浏览器调用NodeJS,这稍微复杂一些,但可以使用jrpc-oo。
如果你想在浏览器或NodeJS中执行,那么你可以将c++编译成WASM,并在浏览器或NodeJS中加载该模块,在那里执行c++。这个WASM回购举例说明了如何做到这一点。我将在这里展开WASM仓库中的关键代码。
创建一些c++代码并声明WASM绑定,例如(从文件include/Test.H和src/Test.C):class Test {
public:
void sayHello(){
printf("Hi, my name is test'n");
}
};
#include <emscripten/bind.h>
EMSCRIPTEN_BINDINGS(Test_ex) {
emscripten::class_<Test>("Test")
.function("sayHello", &Test::sayHello)
;
}
编译下来,你现在可以在NodeJS中运行它(从文件 NodeJS/WASMTestNode.js):
libWASM = require('./libwasmNode.js');
libWASM().then((mod)=>{
libWASM = mod;
let test = new libWASM.Test;
test.sayHello();
});
在浏览器中也可以使用WASM代码。要做到这一点,首先导入WASM库(从文件webcomponent/libWASM.js):
import modProm from './libwasm.js';
然后创建web组件并编译WASM,然后执行c++方法Test::sayHello
(从文件webcomponent/libWASM.js):
import { LitElement } from 'lit';
export class LibWASM extends LitElement {
constructor() {
super();
modProm().then((mod)=>{
this.libWASM = mod; // for rendered WASM that delays
this.WASMReady();
})
}
WASMReady(){
console.log('LibWASM.libWASM module compiled and ready to go.')
let test = new this.libWASM.Test;
test.sayHello();
}
}
这个代码示例在参考的repo中实现。
或者,第三种方法是只使用本参考库中的c++、SWIG和nodejs。
如果你想从浏览器中执行NodeJS,或者使用一种不同的方法将c++集成到NodeJS中,你也可以查看这个SWIG和jrpc-oo参考,它不仅可以在NodeJS中执行,还可以在浏览器中调用NodeJS。
在JavaScript中也有其他的方法来执行c++,但是在这个答案中演示的方法是相当直接的,要么依赖于WASM绑定,要么依赖于SWIG抽象,这使得你的原始代码成为标准的c++。
- electronic BrowserWindow的最小高度和宽度在hide()show()方法之后不起作用
- 有没有任何方法可以将控制器从文件加载到ui路由器$stateProvider中
- 数组在递归方法中设置为null
- 打破承诺链的好方法是什么
- 在使用Polymer'加载所有json文件后执行方法;s的核心ajax
- 使用“;这个“;JavaScript原型方法中的关键字
- 序列化数据属性中对象的最可靠方法
- 使用Objective-C的JavaScript注入方法
- 有没有一种方法可以添加相同的项目val=“0”;4〃;到JavaScript中数组的每个对象
- 有没有一种方法可以防止img get请求使用css或js发生
- Javascript,有没有一种方法可以将数组写成没有逗号或空格的单个文本字符串
- toBoolean方法类似于toString
- 如何在单击复选框后调用控制器方法
- 是否有任何方法可以使用jQuery替换在数组中定义值的文本
- 递归使用 eval() 是检查程序执行的好方法吗?
- 如何在webView,Android中从@JavascriptInterface方法调用Javascript
- toLocaleDateString和toLocaleString方法不尊重机器时区
- 有条件更新d3.js力图中节点的最佳方法
- TypeError:在不兼容的接收器nodejs上调用了方法Uint8Array.length
- jQuery插件-从插件中调用公共方法