Question

I am confused about the ref count in npapi. Mostly, I don't know which method will increase ref count. Can anyone explain in detail about this? For the convenience, I listed most common used NPN_* functions here and my own understanding:

NPN_CreateObject: set ref count to 0

NPN_RetainObject: inc ref count

NPN_ReleaseObject: dec ref count

NPN_Evaluate: ?? (in case return an NPObject*)

NPN_GetValue: ?? (in case return an NPObject*)

NPN_SetValue: ?? (in case set to an NPObject*)

NPN_GetProperty: ?? (in case return an NPObject*)

NPN_SetProperty: ?? (in case set to an NPObject*)

NPN_RemoveProperty: ??

NPN_Enumerate: ??

NPN_Construct: ??

another thing: is npapi do nested release? (In case NPObject* with a property of NPObject*, release parent will decrease the ref count of child).

Thanks.

Was it helpful?

Solution

There isn't room in comments to answer your question in the comment well, so I'll put it in another answer.

Any time your code gets an NPObject from a NPObject function (one of those you mentioned above), you should Release that NPObject when you're done with it. (that could be immediately, or you could save it for awhile and release it when your object gets destroyed). The same holds true with a NPVariant. It does not hold true with the arguments passed into your Invoke function, but the return value you set will get released by the browser when it's done.

When you call NPN_GetValue and get an NPObject from there, that also has to be released. This means that when the browser calls NPP_GetValue, it will release your NPObject when it's done. If you want to create a new NPObject every time the browser calls NPP_GetValue to get your NPObject, then you don't have to call NPN_RetainObject on it; the assumption in the NPAPI example is that you are saving a copy of your NPObject so that it doesn't get deleted until your plugin object gets deleted.

Since the browser will call Release for every time that it calls NPP_GetValue to get your NPObject, you need to make sure that the refcount is incremented before you return it. The reason you don't have to call it twice in the case that you're going to keep it is that NPN_CreateObject does an implicit Retain before it returns your object.

I have written up a more detailed explanation here:

OTHER TIPS

First, to correct a misconception: NPN_CreateObject sets the refCount to 1, not to 0. Then, when you call NPN_RetainObject it increments the refcount, and NPN_ReleaseObject will decrement it. If ReleaseObject decrements the refcount to 0, it will also free it by calling the deallocate function from your NPClass (which should delete the NPObject after doing any needed cleanup)

see: https://developer.mozilla.org/En/NPClass

beyond that, a good general rule of thumb for any of the other NPClass functions is that any time you put an NPObject in a NPVariant, you need to call NPN_RetainObject. To remember this, simply remember that when you're done with an NPVariant (one that you have used and are done with, not one that was passed as a return value), you call NPN_ReleaseVariantValue, which will release the NPString data if it's a string or the NPObject if it's an object.

So from any of the other methods, if you are returning an NPObject, you need to call NPN_RetainObject before you stuff it into the NPVariant. Also, if you save a copy of the NPObject, you should call NPN_RetainObject on it and NPN_ReleaseObject when you're done saving it. It also bears mentioning that you should never call any NPN_ method from a thread other than the main thread.

Does that help?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top