HandleScope v8使用需要将值返回到js函数的低级音频回调来解决问题

时间:2016-09-19 20:13:45

标签: c++ node.js audio v8 node.js-addon

请原谅我的文字墙,但这是一个相当具体的用例,给我带来了麻烦。我查看了v8文档,创建了一些测试以确保工作正常,但在汇编时会弹出问题。

我正在使用Node.js的音频系统,目前正在使用portAudio进行测试。定义回调&从Node获取音频不是问题。当我需要时出现问题:

  • 将音频矢量数据带入节点;
  • 调用用户定义的js函数,该函数将音频数据从portAudio回调转发到Node。

我在初始化期间创建了一个新的Isolate,供音频回调使用(将用于高优先级音频线程的音频回调):

Isolate::CreateParams cp;
cp.array_buffer_allocator = new AudiioArrayBufferAllocator();
auto callbackIsolate = Isolate::New( cp );
std::cout << "storing function ...\n";
callback.Reset( callbackIsolate, Local< Function >::Cast( args[ 5 ] ) );

其中callback

Persistent< Function > callback; 
// js function to hand the audio input to

我们可以在初始化函数中测试这个回调,如下所示:

/// test the callback:
// if below seems odd, see // https://strongloop.com/strongblog/node-js-v0-12-c-apis-breaking/
auto callbackHandle = Local< Function >::New( isolate, callback ); 
// define function arguments & call the function:
Local< Value > arguments[] = { Number::New( isolate, 3.14159 ) };
callbackHandle->Call( Null( isolate ), 1, arguments );

从Node调用该函数会导致:

a = require('./build/Release/audiio');
{ audioDeviceInfo: [Function: audioDeviceInfo],
  initialize: [Function: initialize],
  wrapup: [Function: wrapup],
  updateBuffer: [Function: updateBuffer] }
> a.initialize(2, 2, 44100, 1024, '', function(v){ console.log(v); });
storing function ...
2016-09-19 12:40:08.325 node[39985:4071059] 12:40:08.325 WARNING:  140: This application, or a library it uses, is using the deprecated Carbon Component Manager for hosting Audio Units. Support for this will be removed in a future release. Also, this makes the host incompatible with version 3 audio units. Please transition to the API's in AudioComponent.h.
3.14159

(文本的一部分是由于portAudio,它并不重要,但是看到PortAudio齿轮搅拌很有用......)

在PortAudio Callback中,我们需要调用JS函数,该函数将(最终)从输入接收样本值数组。我在这里包含完整的代码。请注意,传递给音频回调的userData给出了我在初始化期间定义的callbackIsolate

static int nodeAudioCallback( const    void* input,
                                       void* output,
                              unsigned long numFrames,
                              const    PaStreamCallbackTimeInfo* /* timeInfo */,
                                       PaStreamCallbackFlags /* staticFlags */,
                                       void* userData )
{
    auto isolate = static_cast< Isolate* >( userData );
    std::cout << "static_cast< Isolate* > ok.\n";
    Isolate::Scope isolateScope( isolate );
    std::cout << "Isolate::Scope ok\n";
    std::cout << "isolate is " << ( ( isolate == nullptr ) ? "" : "NOT" ) << " nullptr\n";

    Locker lock( isolate );
    HandleScope scope( isolate );
    std::cout << "Locker lock( isolate ) ok.\n";

    // 2. forward the input buffer into the Node callback:
    Local< Value > result[] = { Number::New( isolate, 3.14159 ) };

    std::cout << "Generating a local callbackHandle ... \n";
    auto callbackHandle = Local< Function >::New( isolate, callback );
    std::cout << "Attempting to call the local callbackHandle... \n";
    auto returned = callbackHandle->Call( Null( isolate ), 1, result );
}

我确定我是这个白痴的人,但错误信息有点神秘,我不确定如何解决:

> a = require('./build/Release/audiio');
{ audioDeviceInfo: [Function: audioDeviceInfo],
  initialize: [Function: initialize],
  wrapup: [Function: wrapup],
  updateBuffer: [Function: updateBuffer] }
> a.initialize(2, 2, 44100, 1024, '', function(v){ console.log(v); });
storing function ...
2016-09-19 12:56:31.341 node[40063:4089863] 12:56:31.341 WARNING:  140: This application, or a library it uses, is using the deprecated Carbon Component Manager for hosting Audio Units. Support for this will be removed in a future release. Also, this makes the host incompatible with version 3 audio units. Please transition to the API's in AudioComponent.h.
3.14159
undefined
> static_cast< Isolate* > ok.
Isolate::Scope ok
isolate is NOT nullptr
Locker lock( isolate ) ok.
Generating a local callbackHandle ... 
Attempting to call the local callbackHandle... 

#
# Fatal error in v8::HandleScope::CreateHandle()
# Cannot create a handle without a HandleScope
#

Illegal instruction: 4

在我看来,错误消息所引用的HandleScope必须与我在上面的回调函数中定义的HandleScope不同。

试图:

  1. 在初始化和输入中输入callbackIsolate;在调用callback.Reset之前定义一个HandleScope(无变化)
  2. 尝试将函数调用更改为MaybeValue返回调用,该调用带有上下文,导致Bus Error: 10,这意味着我真的搞乱了记忆访问。
  3. 由于我在一个相当特别的事情上寻求帮助,我可以在这里看到完整的代码:https://gist.github.com/ilzxc/7ebda4f61e844804459d1fc3fa72f1e4 - 但我也很自觉地问其他人要看一堆代码。

    任何建议都会得到真诚的赞赏。

0 个答案:

没有答案