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.
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:
http://colonelpanic.net/2009/12/memory-management-in-npapi
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?
Related
I have created a system, within which I am instancing kinematic bodies (2D). These have scripts attached. When I call the functions within these, all is GENERALLY okay. However randomly, with wildly different wait times for it to happen (sometimes it never does), the system will crash, saying that the function, that has been working fine, is does not exist within Area2D. I have no clue why this can happen, can anyone give me any help with this.
The actual error code Invalid call. Nonexistent function 'move' in base 'Area2D'
Thanks
Add check for method existence before you call method.
Let's say you call move method for obj variable (replace it with your own).
Now call to the move method should look like this:
if obj.has_method("move"):
obj.move()
Docs
According to Microsoft documentation:
"You can free this [pwfx] structure immediately after passing it to waveOutOpen."
But this code dosen't seem to agree:
pwfx=new WAVEFORMATEX;
pwfx->wFormatTag=WAVE_FORMAT_PCM;
pwfx->nChannels=2;
pwfx->nSamplesPerSec=SPS;
pwfx->nAvgBytesPerSec=SPS*2;
pwfx->nBlockAlign=2;
pwfx->wBitsPerSample=8;
mmres=waveOutOpen(&ghwo,uDeviceID,pwfx,dwCallback,dwCallbackInstance,fdwOpen);
delete pwfx;
The only problem I can see in the code you provided is that you did not fully initialise the struct. You did not initialise cbSize which in this instance must be set to 0.
Given that you are not allocating any extra data at the end of this struct, there's no need to allocate it in the heap.
It's entirely plausible that the problem lies in the other parameters that you pass to the function. We can't see any details of them, and therefore can't comment.
You don't need to new or delete anything. You can just do:
WAVEFORMATEX wfx = { };
wfx.wFormatTag=WAVE_FORMAT_PCM;
...
mmres=waveOutOpen(&ghwo,uDeviceID,&wfx,dwCallback,dwCallbackInstance,fdwOpen);
Does that help at all?
I setup a subject and then put some methods on it. It seems to work as intended until it gets to .switch() which I thought would simply keep track of the last call. I get the error Property 'subscribe' does not exist on type 'ApiChange' It seems to convert it to type ApiChange from an observable. I don't understand this behavior. Should I be using a different operator?
Service:
private apiChange = new Subject<ApiChange>();
apiChange$ = this.apiChange.asObservable().distinctUntilChanged().debounceTime(1000).switch();
Component:
this.service.apiChange$.subscribe(change => {
this.service.method(change);
});
.debounceTime(1000) will already assure you will only get a maximum of one value emitted from your observable chain per second. All the values preceding the 1 second quiet time will already be discarded.
With a simple Subject (not a ReplaySubject), past values are not provided to subscribers anyway.
You probably just want to skip the .switch() and enjoy the chain without it.
I am using a 3rd party library that invokes a Core Foundation function.
Since that lib has a bug, passing incorrect values to a CF function, I need to intercept that call to fix the passed values.
How do I hook into the CF function call so that I can look at the passed parameters, change them and then call the actual (original) function?
I have the impression I can get to the actual function with the CFBundleGetFunctionPointerForName, passing CFBundleGetMainBundle()as the first parameter and the name of the CF function as the second parameter.
In my particular case, that would be:
void *p = CFBundleGetFunctionPointerForName (CFBundleGetMainBundle(), "CFRunLoopTimerCreate");
But that returns NULL.
I also tried this:
void *p = CFBundleGetFunctionPointerForName (CFBundleGetBundleWithIdentifier("com.apple.Cocoa"), "CFRunLoopTimerCreate");
That returns a non-null value but it still does not appear to be a pointer I could change but rather the actual starting address of the function's code.
So, how do I get an address of a function pointer to an imported API function that I can save and then change to point to my intercepting function? Or how else could I hook into an imported function?
CFBundleGetFunctionPointerForName will just return the address of a function in a given bundle; this will never let you change the destination of calls to the function. If you really want to do something like that, please refer to Is it possible to hook API calls on Mac OS? Note that this is highly not recommended.
After doing promisify on a specific function with bluebird - is it possible to get a reference to the original function that was promisified?
Why: I'm using a helper that gets argument names from the function and on promisified functions it gives back (_arg0, _arg1, _arg2), I was hoping it was possible to get the original function signature from somewhere.
No, you can work around it though.
If it is promisified with promisifyAll you can access it without the Async suffix - otherwise, you'd have to do it yourself:
var promisified = Promise.promisify(cbFunction);
promisified.original = cbFunction;
// access as promisified.cbFunction from that point on.
Otherwise, the original function is captured via a closure and you can't reliably access it. In all honesty you probably shouldn't since that'd meddle with minification anyway.