2009-12-23 51 views
2

我对npapi中的ref计数感到困惑。大多数情况下,我不知道哪种方法会增加参考计数。任何人都可以详细解释这个吗?为了方便,我列出了最常用的NPN_ *这里的功能和我自己的理解:何时在npapi插件中释放对象

NPN_CreateObject:设置引用计数为0

NPN_RetainObject:INC引用计数

NPN_ReleaseObject:十二月引用计数

NPN_Evaluate:?? (在返回NPObject *的情况下)

NPN_GetValue:?? (在返回NPObject *的情况下)

NPN_SetValue:?? (如果设置为NPObject *)

NPN_GetProperty:?? (在返回NPObject *的情况下)

NPN_SetProperty:?? (如果设置为NPObject *)

NPN_RemoveProperty:??

NPN_Enumerate:??

NPN_Construct:??

另一件事:是npapi做嵌套发布? (如果NPObject *具有NPObject *的属性,则释放父项将减少子项的引用计数)。

谢谢。

+1

这也可能有帮助:http://jldupont.blogspot.com/2009/11/notes-on-npapi -based-plugins.html – jldupont 2009-12-23 20:24:26

回答

4

评论中没有评论空间来回答你的问题,所以我会把它放在另一个答案。当你的代码从一个NPObject函数(你在上面提到的那个函数之一)中获得一个NPObject时,你应该在你完成它时释放该NPObject。 (可以立即,或者你可以保存它一段时间,并释放它,当你的对象被破坏)。NPVariant也是如此。它确实是而不是在传入你的Invoke函数的参数中保持为true,但是你设置的返回值在浏览器完成时会被释放。

当你调用NPN_GetValue并从那里得到一个NPObject时,它也必须被释放。这意味着当浏览器调用NPP_GetValue时,它将在完成时释放NPObject。如果你想在每次浏览器调用NPP_GetValue来获得你的NPObject时创建一个新的NPObject,那么你不必在其上调用NPN_RetainObject; NPAPI示例中的假设是,您要保存NPObject的副本,以便在删除插件对象之前不会被删除。

由于浏览器在每次调用NPP_GetValue获取您的NPObject时都会调用Release,因此您需要确保在返回它之前增加了refcount。在你要保留它的情况下,你不必调用它两次的原因是NPN_CreateObject在返回对象之前做了隐式保留。

我在这里写了一个更详细的解释:

+0

谢谢。我想我终于明白了。纠正我,如果我错了。例如:如果您通过NPN_Evaluate获得对象A,然后通过NPN_SetProperty(npp,B,identifier,A)将其设置为另一个对象B,则您仍然必须并且可以立即NPN_ReleaseVariableValue(A)(您销毁您创建的内容) 。但是,您不必担心B尝试访问属性A时会发生seg故障,因为浏览器引用计数为NPN_SetProperty中的A.最后一句话,就是浏览器实现嵌套版本的方式。 – liuliu 2009-12-24 21:33:16

+0

我不确定我是否完全理解你的意思。如果你得到的是一个NPVariant的对象A,那么是的,你需要释放它,但是直到你完成它。一旦你释放,你必须假设它不再可以访问。是的,如果它正确实现,B应该在SetProperty期间递增引用计数,如果它保存在引用上。任何时候你得到一个参考,保留;任何时候你完成一个,发布。 我写了一篇关于这个主题的博客文章,详细一点:http://colonelpanic.net/2009/12/memory-management-in-npapi/ – taxilian 2009-12-24 22:14:29

3

首先,要纠正一个误解:NPN_CreateObject将refCount设置为1,而不是0.然后,当您调用NPN_RetainObject时,它会增加引用计数,并且NPN_ReleaseObject会将其递减。如果ReleaseObject递减引用计数为0,它也将通过从NPClass呼吁解除分配功能

见(做任何所需的清理之后,应该删除NPObject)无它:https://developer.mozilla.org/En/NPClass

除此之外,一个优秀的将军任何其他NPClass函数的经验法则是,只要您将NPObject放入NPVariant中,就需要调用NPN_RetainObject。要记住这一点,只要记住当你完成一个NPVariant(一个你已经使用和完成的,而不是一个作为返回值传递的)时,你可以调用NPN_ReleaseVariantValue,它将释放NPString数据,如果它是一个字符串或NPObject,如果它是一个对象。

因此,从任何其他方法中,如果您要返回一个NPObject,则需要在将其填充到NPVariant中之前调用NPN_RetainObject。另外,如果保存了NPObject的副本,则应在完成保存后调用NPN_RetainObject和NPN_ReleaseObject。它还提到,你永远不应该从主线程以外的线程调用任何NPN_方法。

这有帮助吗?

+1

感谢您的详细解答。所以,如果我使用NPN_GetValue,不需要释放,但是如果我使用NPN_Evaluate,我应该释放变体。 但是,关于NPN_CreateObject,如果它已经将ref count设置为1,为什么在代码中我们必须: if(this-> npobj!= NULL) retval =(NPObject *)this-> npobj; else retval =(NPObject *)MyScriptableNPObject :: NewObject(this-> npp); NPN_RetainObject(retval); 它创建后再次保留它,这不会使ref数到2(第一次调用getScriptableObject)? – liuliu 2009-12-24 18:05:54