在我的NPAPI插件中,某些对象具有可读写的“onEvent”属性,该属性在某些事件上会被调用。

我的Javascript代码中的内容如下所示:

myObject.onEvent = function( event ) {
    console.log("Event: " + event );
}

// if I put this next line, the next call to the 'onEvent' handler will SIGBUS
// when there's no RetainObject() in the getter.
console.log("Event handler : " + myObject.onEvent);

在插件的C++端,我有这样的代码:
bool MyPluginObject::getOnEvent(NPIdentifier id, NPVariant *result)
{
    if( _onEvent )
    {
        OBJECT_TO_NPVARIANT( _onEvent, *result);
        NPN_RetainObject( _onEvent ); // needed ???? why??
    }
    else
        VOID_TO_NPVARIANT(*result);

    return true;
}

bool MyPluginObject::setOnEvent( NPIdentifier id, const NPVariant *value )
{
    if ( value && NPVARIANT_IS_OBJECT( *value ) )
    {
        if( _onEvent != NULL )
        {
            // release any previous function retained
            NPN_ReleaseObject( _onEvent );
        }

        _onEvent = NPVARIANT_TO_OBJECT( *value );
        NPN_RetainObject( _onEvent ); // normal retain

        return true;
    }
    return false;
}

void MyPluginObject::onEvent(void)
{
    NPVariant event = [...];

    if ( _onEvent!= NULL )
    {
        NPVariant retVal;
        bool success = NPN_InvokeDefault( _Npp, _onEvent, &event, 1, &retVal );
        if( success )
        {
            NPN_ReleaseVariantValue(&retVal);
        }
    }
}

奇怪的是,我一直在努力解决SIGBUS问题,一旦我在 setter/getter 中添加了NPN_RetainObject()(如您在上面看到的),一切就很好了。

我在声明中没有找到Mozilla doc中需要它,也没有在Taxilian很棒的doc about NPAPI中得到它。

我不明白:当浏览器请求保留的属性时,为什么我必须再次保留它?

在调用InvokeDefault()时,是否应该保留该函数?但是,为什么呢?我已经说过要保留它。
getProperty()InvokeDefault()是否实际上在不告诉我的情况下做了NPN_ReleaseObject()

最佳答案

您始终必须使用NPAPI保留对象输出参数,这不特定于属性 getter 。

在您的特定情况下,对象可能仍然存在,但在一般情况下不会:
考虑将一个您不打算从插件中保留下来的对象返回给调用者。您必须将所有权转移给调用方,并且不能返回保留计数为0的对象。

关于c++ - NPAPI:需要两次RetainObject()一个处理程序,否则SIGBUS,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11824065/

10-10 20:23