我正在尝试将从JavaScript传递的对象存储到void *
中的Node.js插件中。我似乎无法编译这个;使用node-gyp构建error: no matching function for call to 'Cast'
。
我正在尝试做的长版本是编写一个运行Csound的Node.js插件。从鸟瞰的角度来看,Csound的C函数可以将指向不透明的Csound结构的指针作为(通常)第一个参数。此结构包含void *
到“hostData
”,由托管Csound的程序设置的任意数据。 Csound所做的一些事情,比如发布消息,在这种情况下使用回调函数指针进行修改。我需要一个地方来存储Csound的每个实例的回调,所以我试图让某人将hostData
设置为来自JavaScript的对象,但我也想将Csound实例的回调设置为{{3} } hostData
这个对象。
我认为代码需要看起来像
#include "csound.h"
#include <node.h>
static void CsoundMessageCallback(CSOUND *Csound, int attributes,
const char *format, va_list valist)
{
// Call the JavaScript function we stored in the hostData of Csound.
}
static void _wrap_csoundSetMessageCallback(
const v8::FunctionCallbackInfo<v8::Value>& args)
{
v8::HandleScope scope(v8::Isolate::GetCurrent());
CSOUND *Csound;
// Pretend we get the Csound instance from args[0] here. This is actually done
// by SWIG <http://www.swig.org>.
// This does not compile. csoundGetHostData() returns a void *, but I’m assuming
// hostData was set to an object from JavaScript.
v8::Persistent<v8::Object> hostData =
v8::Persistent<v8::Object>::Cast(csoundGetHostData(Csound));
hostData.SetHiddenValue(
v8::String::New("CsoundMessageCallback"),
v8::Persistent<v8::Function>::Cast(args[1])
);
csoundSetMessageCallback(Csound, CsoundMessageCallback);
}
我猜我需要仔细看看V8的内部字段,但我真的不确定。
答案 0 :(得分:2)
通常我在这种情况下所做的就是编写一个包装器C ++类(继承自node的ObjectWrap类),该类存储指向我正在包装的任何C / C ++类的实例的指针,并具有各种公共方法与该实例进行交互。
当从JS land调用new
时,会创建一个包装C ++类的新实例并与新的JS对象相关联。然后你有JS函数启动任何利用包装库的回调的异步任务。
从那里只需要从包装库的回调中调用uv_async_send()
来发出主线程信号,然后从uv_async回调中调用JS回调。
您可以看到所有这些here的示例(特别是在Windows特定的部分中):
Pcap
类包含pcap_t
指针(对您来说是CSOUND
指针)。Pcap
时,我wrap a new C++ class instance。uv_async_t
将the callback设置为uv_async_send()
以及associates the user data pointer到类实例以便于访问。如果你愿意的话,可以在调用new
期间进行初始化,而不是像我自己做的那样只执行一次单独的原型函数(open()
)。就存储JS回调而言,有不同的方法来处理它。一种解决方案可能是创建一个baton对象,该对象存储JS回调的持久副本和包装器类实例,并将该接力棒存储在uv_async_t
的用户数据指针中。这意味着为每个请求创建一个新的uv_async_t
(与我上面给出的示例不同)。