在 void * for Node.js Addon 中检索和存储 V8 对象
Retrieving and storing V8 object in void * for Node.js Addon
我正在尝试将从 JavaScript 传递到 Node.js 插件的对象存储在 void *
中。我似乎无法编译它;使用 node-gyp 构建会产生 error: no matching function for call to 'Cast'
.
我正在尝试做的长版本是编写一个运行 Csound 的 Node.js 插件。从鸟瞰图来看,Csound 的工作原理是使用 C 函数,这些函数将指向不透明 Csound 结构的指针作为(通常)第一个参数。该结构包含 void *
到“hostData
”,由托管 Csound 的程序设置的任意数据。 Csound 做的一些事情,比如发布消息,是用回调修改的——在这种情况下是函数指针。我需要一个地方来存储每个 Csound 实例的回调,所以我试图让某人将 hostData
设置为来自 JavaScript 的对象,但我还想将 Csound 实例的回调设置为hidden properties 在这个 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 的内部字段,但我真的不确定。
通常我在这种情况下所做的是编写一个包装器 C++ class(继承自节点的 ObjectWrap class),它存储指向任何实例的指针 C/C++ class 我正在包装并有多种 public 方法与该实例进行交互。
当从 JS 领域调用 new
时,将创建包装器 C++ class 的新实例并将其与新的 JS 对象相关联。然后你有 JS 函数来启动任何使用包装库回调的异步任务。
从那里开始,只需从包装库的回调中调用 uv_async_send()
向主线程发出信号,然后从 uv_async 回调中调用 JS 回调即可。
您可以查看所有这些 here 的示例(尤其是 Windows 特定部分):
Pcap
class 持有一个 pcap_t
指针(对你来说是 CSOUND
指针)。
- 当一个新的
Pcap
从 JS 土地创建时,我 wrap a new C++ class instance.
- Initialize a
uv_async_t
which sets up the callback to fire on uv_async_send()
and also associates the user data pointer 到 class 实例以便于访问。如果需要,您可以在调用 new
期间执行此初始化,而不是像我所做的那样使用单独的原型函数 (open()
),因为初始化只发生一次。
- 然后从the wrapped library's callback, I signal主线程。
- 从 uv_async 回调中,我可以 access the wrapper class instance and use V8 functions safely. Although in my particular case, I have another callback 使用 V8 函数。但是,您可以在 uv_async 回调中安全地使用它们。
就存储 JS 回调而言,有不同的处理方法。一种解决方案可能是创建一个指挥棒对象,该对象存储 JS 回调的持久副本和包装器 class 实例,并将该指挥棒存储在 uv_async_t
的用户数据指针中。这意味着为每个请求创建一个新的 uv_async_t
(这与我上面给出的示例不同)。
我正在尝试将从 JavaScript 传递到 Node.js 插件的对象存储在 void *
中。我似乎无法编译它;使用 node-gyp 构建会产生 error: no matching function for call to 'Cast'
.
我正在尝试做的长版本是编写一个运行 Csound 的 Node.js 插件。从鸟瞰图来看,Csound 的工作原理是使用 C 函数,这些函数将指向不透明 Csound 结构的指针作为(通常)第一个参数。该结构包含 void *
到“hostData
”,由托管 Csound 的程序设置的任意数据。 Csound 做的一些事情,比如发布消息,是用回调修改的——在这种情况下是函数指针。我需要一个地方来存储每个 Csound 实例的回调,所以我试图让某人将 hostData
设置为来自 JavaScript 的对象,但我还想将 Csound 实例的回调设置为hidden properties 在这个 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 的内部字段,但我真的不确定。
通常我在这种情况下所做的是编写一个包装器 C++ class(继承自节点的 ObjectWrap class),它存储指向任何实例的指针 C/C++ class 我正在包装并有多种 public 方法与该实例进行交互。
当从 JS 领域调用 new
时,将创建包装器 C++ class 的新实例并将其与新的 JS 对象相关联。然后你有 JS 函数来启动任何使用包装库回调的异步任务。
从那里开始,只需从包装库的回调中调用 uv_async_send()
向主线程发出信号,然后从 uv_async 回调中调用 JS 回调即可。
您可以查看所有这些 here 的示例(尤其是 Windows 特定部分):
Pcap
class 持有一个pcap_t
指针(对你来说是CSOUND
指针)。- 当一个新的
Pcap
从 JS 土地创建时,我 wrap a new C++ class instance. - Initialize a
uv_async_t
which sets up the callback to fire onuv_async_send()
and also associates the user data pointer 到 class 实例以便于访问。如果需要,您可以在调用new
期间执行此初始化,而不是像我所做的那样使用单独的原型函数 (open()
),因为初始化只发生一次。 - 然后从the wrapped library's callback, I signal主线程。
- 从 uv_async 回调中,我可以 access the wrapper class instance and use V8 functions safely. Although in my particular case, I have another callback 使用 V8 函数。但是,您可以在 uv_async 回调中安全地使用它们。
就存储 JS 回调而言,有不同的处理方法。一种解决方案可能是创建一个指挥棒对象,该对象存储 JS 回调的持久副本和包装器 class 实例,并将该指挥棒存储在 uv_async_t
的用户数据指针中。这意味着为每个请求创建一个新的 uv_async_t
(这与我上面给出的示例不同)。