1

stringグローバル イベント マネージャーがあり、ラムダでイベント名をリッスンできます。

// somewhere in the ModuleScript class
Event->Listen("WindowResize", [=]{
    // ...
});

ここで、JavaScript からもイベントに登録したいと思います。したがって、私はこのコールバックを書きました。

v8::Handle<v8::Value> ModuleScript::jsOn(const v8::Arguments& args)
{
    // get pointer to class since we're in a static method
    ModuleScript *module = (ModuleScript*)HelperScript::Unwrap(args.Data());

    // get event name we want to register to from arguments
    if(args.Length() < 1 || !args[0]->IsString())
        return v8::Undefined();
    string name = *v8::String::Utf8Value(args[0]);

    // get callback function from arguments
    if(args.Length() < 2 || !args[1]->IsFunction())
        return v8::Undefined();
    v8::Handle<v8::Function> callback =
        v8::Local<v8::Function>::Cast(args[1]->ToObject());

    // register event on global event manager
    module->Event->Listen(name, [=]{
        // create persistent handle so that function stays valid
        // maybe this doesn't work, I don't know
        v8::Persistent<v8::Function> function =
            v8::Persistent<v8::Function>::New(args.GetIsolate(), callback);
        // execute callback function
        // causes the access violation
        function->Call(function, 0, NULL);
    });

    return v8::Undefined();
}

イベントがトリガーされると、アプリケーションはアクセス違反でクラッシュします。私の考えでは、現時点で関数オブジェクトが有効ではないか、JavaScript スコープの問題であると考えられます。しかし、私はそれを理解できませんでした。

アクセス違反の原因とそれを克服する方法は?

4

1 に答える 1

2

ここにはいくつかの潜在的な問題があると思います。

まず、終了後に JavaScript 関数を保持するために永続ハンドルを使用していませんModuleScript::jsOn()。イベント ハンドラーが呼び出されるまでに、関数がなくなっている可能性があります。callback永続的なハンドルを作成することを検討してください。

次に、イベント ハンドラーは、JavaScript 関数を呼び出す前に、適切な V8 コンテキストに入る必要があります。アーキテクチャによっては、明示的にロックして V8 アイソレートに入る必要がある場合もあります。

第 3 に (これは特定のシナリオでは問題にならない場合があります)、V8 アイソレートの有効期間を管理する必要があります。イベント マネージャーがバックグラウンド スレッドでイベントを発生させる場合は、イベント ハンドラーが別のスレッドから Isolate が破棄されないようにする必要があります。残念ながら、これは V8 API があまり役に立たない領域の 1 つです。

第 4 に、リークを防ぐために、イベント ハンドラーは、関数を呼び出した後に永続的な関数ハンドルを破棄する必要があります。

幸運を!

于 2013-06-20T12:41:24.350 に答える