![](/img/trans.png)
[英]Using NAN, how do I call Javascript from a C++ function that's not a NAN_METHOD?
[英]How to call a C++ method from javascript
我有一個 C++ 方法(該角色正在殺死一些進程)。 她需要 2 個參數: a hostname and a port
。
另一方面,我正在開發一個在 Google Chrome 上運行的網絡應用程序(使用 Nodejs 和 AngularJS)。
當我通過瀏覽器單擊一個按鈕時,我希望能夠通過我的app.js
文件調用 C++ function。
我還沒有找到如何將 javascript 與 C++ “綁定”。
編輯:我認為這個鏈接可能非常有用如何使用 node.js 中的 C++ 庫?
您可以使用Google's V8
。 V8
是谷歌的開源JavaScript
引擎。 V8
可以standalone
運行,也可以embedded
到任何C++
應用程序中。
以下來自github演示的示例,將C++
類與Google V8
綁定。 v8_wrap_class.cpp - 作者是尼古拉斯
/*
* 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;
}
你可以向你的服務器發一個ajax請求,並在后端調用c ++,也許在php中。 或者這可能很有用https://code.google.com/p/tiny-js/
這個答案給出了在 javascript 中使用 C++ 的四種方法。 所示方法試圖將原始 C++ 保留在標准和簡單的 C++ 實現中。
兩種使用 WASM 的方法和兩種使用 SWIG 和 JRPC 的方法用於給出在 javascript 中執行 C++ 的示例和想法。 詳細地說,這個答案給出了一個在瀏覽器中執行的例子和一個在 nodejs 中使用 WASM 執行的例子。 這個答案的結尾還列出了另外兩種在 javascript 中執行 C++ 的方法,其中一種方法是從瀏覽器調用 nodejs,這種方法稍微復雜一些,但可以使用 jrpc-oo。
如果要在瀏覽器或 nodejs 中執行,則可以將 C++ 編譯為 WASM 並將該模塊加載到瀏覽器或 nodejs 中,在那里執行 C++。 這個WASM repo舉例說明了如何做到這一點。 我將在此處擴展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 delay
this.WASMReady();
})
}
WASMReady(){
console.log('LibWASM.libWASM module compiled and ready to go.')
let test = new this.libWASM.Test;
test.sayHello();
}
}
此代碼示例在參考 repo中實現。
或者,第三種方法是僅使用此參考 repo中的 C++、SWIG 和 nodejs。
如果您想從瀏覽器執行 nodejs 或使用其他方法將 C++ 集成到 nodejs 中,您還可以查看此 SWIG 和 jrpc-oo 參考以執行相同的操作,但不僅在 nodejs 中,還從瀏覽器調用 nodejs .
還有其他方法可以從 javascript 執行 C++,但是此答案中演示的方法相當簡單,並且依賴於 WASM 綁定或 SWIG 抽象,從而將您的原始代碼保留為標准 ZF6F87C9FDCF8B3C3F07F93F1EE872。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.