We have some existing C++ code we want to incorporate into a Firefox
plugin so that Web pages can interact with our C++ using JavaScript
embedded in the Web page. We're not trying to embed SpiderMonkey into
our plugin...rather we need to use the native instance running in
Firefox.
The following link is very helpful in that it acknowledges this can
occur and gives me the IDL I need to begin creating my C++/Javascript
interaction:
http://developer.mozilla.org/en/docs/Creating_JavaScript_callbacks_in_components
But what it doesn't help me with is the C++ behind it. If I create an
"add listener" type of method and provide it with a JavaScript
function as a callback, the several techniques I've tried to actually
invoke the JavaScript method fail with access violations.
Here is some example IDL:
[scriptable, function, uuid(D88A95BC-E5E0-4f61-A740-93B144C83AE9)]
interface IErrorCallback : nsISupports {
boolean onError();
};
[scriptable, uuid(CC148D6D-508E-44c6-8EFD-139619AB9AE9)]
interface nsIMyPlugin : nsISupports
{
...
void AttachErrorCallback(in IErrorCallback fn);
void NotifyError();
...
}
In my C++, the AttachErrorCallback method stores the incoming function
pointer in an instance variable (a class field so we retain state).
Later, on error notification, the NotifyError method will take this
cached JavaScript pointer and invoke the callback:
void MyClass::NotifyError(void)
{
PRBool ok;
cachedFnPtr->OnError(&ok);
}
This fails with an access violation. I've checked and the pointer
isn't NULL, so it's not being cleared.
If I try various combinations of nsCOMPtr wrapping, those fail as
well:
nsCOMPtr<IErrorCallback> js_callback = cachedFnPtr; // <-- access
violation
js_callback->OnError($ok);
Or:
nsCOMPtr<IErrorCallback>
js_callback(do_QueryInterface(cachedFnPtr)); // <-- access violation
js_callback->OnError($ok);
I'm sure I'm missing something simple, and probably obvious to expert
Firefox devs...any ideas?
Any help or guidance is greatly appreciated! Thanks...!
Does that field keep a ref count on the object? If not, it'll likely
be destroyed before you call it later, and you'll be calling through a
dangling pointer.
nsCOMPtr<IErrorCallback> cachedFnPtr; // will keep a ref
IErrorCallback *cachedFnPtr; // no ref kept unless you do it manually -- avoid!
Mike
Oh...you know? It doesn't! You were correct, as was I (it was
something obvious).
That did the trick. Thanks!