2

我正在尝试将从 JavaScript 传递到 Node.js 插件的对象存储在void *. 我似乎无法编译它;使用 node-gyp 构建会产生error: no matching function for call to 'Cast'.

我正在尝试做的长版本是编写一个运行 Csound 的 Node.js 插件。从鸟瞰的角度来看,Csound 使用 C 函数工作,该函数将指向不透明 Csound 结构的指针作为(通常)第一个参数。这个结构包含一个void *“<code>hostData”,由托管 Csound 的程序设置的任意数据。Csound 所做的一些事情,比如发布消息,是用回调修改的——在这种情况下是函数指针。我需要一个地方来存储每个 Csound 实例的回调,所以我试图让某人hostData从 JavaScript 中设置一个对象,但我还想将 Csound 实例的回调设置为该对象的隐藏属性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 的内部字段,但我真的不确定。

4

1 回答 1

2

通常我在这种情况下所做的是我编写了一个包装 C++ 类(从节点的 ObjectWrap 类继承),它存储一个指向我正在包装的任何 C/C++ 类的实例的指针,并有各种公共方法与之交互实例。

new从 JS 领域调用时,包装 C++ 类的新实例被创建并与新的 JS 对象相关联。然后你有 JS 函数来启动任何使用包装库回调的异步任务。

从那里只需uv_async_send()从包装库的回调中调用以向主线程发出信号,然后从 uv_async 回调中调用 JS 回调。

您可以在此处查看所有这些示例(尤其是在 Windows 特定部分中):

就存储 JS 回调而言,有不同的处理方法。一种解决方案可能是创建一个接力棒对象,该对象存储 JS 回调和包装类实例的持久副本,并将该接力棒存储在uv_async_t的用户数据指针中。这意味着uv_async_t为每个请求创建一个新的(这与我上面给出的示例不同)。

于 2015-09-07T16:09:49.823 回答