Patrick McHale wrote:
> 
> Thanks you for your reply - this is the way we wish to proceed and will try
> to implement this. Our problem is that we wish to implement this
> dynamically - so that we do not have to hard code our function names within
> the C++ code.
> 
> We would like to pass our javascript function names somehow in the future.
> In the mean time we have decided to hard code the javascript function names.

You saw Sean Echevarria's answer to your question in the plugins
group, right? If you are doing a plugin and can go that route
then great. Else your callback would need to implement an xpcom
interface in order to use xpconnect to make the call...

> 
> A question I would like to ask - When the interfaces are declared to send /
> receive callbacks - are these using separate uuid numbers. Does this mean
> that I will need to use guidgen to generate a couple more numbers to place
> in the new component interfaces?.

Yes, you'd be declaring interfaces with new iids and shipping an
xpt file and all that. I assume that you'd already be declaring
your interface on which you are going to call your
"theSession.OpenConnection" method. It is the callback's
interface you'd need to add.

> 
> Also if convenient - could you explain more about doing an AddRef on the
> current Listener and using the nsCOMPtr class member. I am
> unsure about this. Is there some information around regarding nsCOMPtr.?
> What is this used for?

The idea is simply that your JS code is going to be passing an
object pointer into the C++ code. If that C++ code is going to
hold onto that pointer for later use then it must add a reference
on that pointer to hold it in place and then release the
reference when it is done with the pointer. This is standard COM
stuff. The nsCOMPtr template class makes this easier (once you
get up to speed using it). There is a manual...

http://www.mozilla.org/projects/xpcom/nsCOMPtr.html

John.

> 
> With Thanks
> 
> Patrick McHale
> Powerlan USA
> 
> "John Bandhauer" <[EMAIL PROTECTED]> wrote in message
> [EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
> > When using xpcom you are encouraged to think in terms of
> > interfaces and objects rather than callback functions -
> > regardless of the programming language you use.
> >
> > So the 'normal' way to do something like this is...
> >
> > // Declare the interface to receive callbacks
> > [scriptable, uuid(...)]
> > interface mynamespaceListener : nsISupports
> > {
> >   void connectionOpened(in PRBool success);
> > };
> >
> > // Declare the interface that will send callbacks.
> > // You need to be able to tell it who to call...
> > [scriptable, uuid(...)]
> > interface mynamespaceNotifier : nsISupports
> > {
> >   // You could use explicit get/set.
> >   // But attributes are easier...
> >   attribute mynamespaceListener connectionListener;
> > };
> >
> > You implemenent the get/set methods of mynamespaceNotifier and do
> > an AddRef on the current listener (an nsCOMPtr class member is
> > good for this).
> >
> > You expose that notifier object ot JS either as a service or more
> > directly by whatever means..
> >
> > Your JS code then creates a JS object that has a connectionOpened
> > method and passes that object to the notifier object by setting
> > the notifier's connectionListener property.
> >
> > There are pleny of styles of doing this, but you might do is
> > something like this...
> >
> > var listener = {
> >   connectionOpened : function(success) {
> >     if (success)
> >       alert("The Connection was made!")
> >     else
> >       alert("The Connection Failed.");
> >   }
> >   // you can add whatever other properties you might want to this
> > object
> > };
> >
> > // assuming that your notifer is a service...
> > var clazz = Components.classes["my_notifier_contractid"];
> > var iface = Components.interfaces.mynamespaceNotifier;
> > var notifier = clazz.getService(iface);
> >
> > notifier.connectionListener = listener;
> >
> > Now in your C++ code you can just call something like...
> >   mListener->ConnectionOpened(PR_TRUE);
> > ...and the call will be routed to the JS code.
> >
> > Note that if you really implement this object in a document then
> > you'd probably want to clear the listener then the page gets
> > unloaded. e.g....
> >   notifier.connectionListener = null;
> > This ought to make your C++ code Release the previous listener
> > and will cause xpconnect to allow the JS object to be garbage
> > collected when there are no other references to it.
> >
> > I hesitate to tell you about it... but if you absolutely *need*
> > the JS code to be called back as a plain function rather than as
> > a method on an object then you *could* use some xpconnect
> > functionality that was very recently added to support legacy DOM
> > event handling. I discourage its use - there is no support for
> > doing this in any other language. The pattern is...
> >
> > // Declare the interface to receive callbacks
> > // ... using the 'function' keyword
> > [function, scriptable, uuid(...)]
> > interface mynamespaceListener : nsISupports
> > {
> >   void connectionOpened(in PRBool success);
> > };
> >
> >
> > In JS you can use a plain function..
> >
> > function WebTerm_ConnectionOpened(success)
> > {/*...*/}
> >
> > The C++ code is the same.
> >
> > You set the callback using:
> > notifier.connectionListener = WebTerm_ConnectionOpened;
> >
> > When the call is made to the callback xpconnect will notice that
> > this is a [function] interface and attempt to call the object as
> > a function rather than lookup a named function property on the
> > object and call that as it would normally do.
> >
> > Note that there is *no* support for...
> >
> > notifier.connectionListener = "WebTerm_ConnectionOpened()";
> >
> > This would imply that xpconnect would need to know how to convert
> > a string into a compiled function. It does not do that. The DOM
> > supports this using a bunch of specialized code.
> >
> > Again, I *really* encourage you to use objects with named methods
> > which make the object meet the requirements of the declared
> > interface rather than use the less supported [function] hack.
> >
> > Also, I just looked at your example below again and realized that
> > I showed you a more generic "set it and forget it" listener
> > pattern. For the specific case you have you could do pretty much
> > what I wrote above, but just declare your OpenConnection method
> > to take an 'in' param of type mynamespaceListener and pass your
> > listener object into the function as a param. Be sure to AddRef
> > and Release the interface pointer appropriately on the C++ side.
> >
> > Also, you may have noticed xpidl's method name leading character
> > upper-casing rules. the deal is that we have history of using
> > LeadingUpperCaseMethods in C++ and leadingLowerCaseMethods in
> > JavaScript. If got decided (with *much* controversy!) a while
> > back to encourage people to declare their interfaces like:
> > "myMethod" in the idl and the C++ header mapping will get
> > "MyMethod" and the JS will use "myMethod". the xpidl compiler,
> > xpconnect and other such dynamic mapping layers deal with making
> > this work right. So anyway, you are encouraged to use the
> > "myMethod" style in your idl method and attribute names.
> >
> > John.
> >
> > Patrick McHale wrote:
> > >
> > > Hi,
> > >
> > > I was wondering about implementing CallBacks - Calling Javascript
> functions
> > > from an XPCOM object. I am not sure about how to correctly implement
> this.
> > > At present I have a Javascript function which I wish to call.
> > >
> > > function WebTerm_ConnectionOpened(success) {
> > > if (success)
> > >       alert("The Connection was made!")
> > > else
> > >       alert("The Connection Failed.");
> > > }
> > >
> > > I also have a function defined to intiate the open connection - with a
> > > Callback function description.
> > >
> > > function OpenConnection(theSession) {
> > >     theSession.OpenConnection(true, 300 ,"WebTerm_ConnectionOpened()");
> > >
> > > The open connection routine works fine - but would like to get the
> CallBack
> > > operation working.  How should the IDL file be setup?.  Is this to be
> > > defined as a inout attribute?.  What is the return parameter needed to
> > > enable a Callback function to work?.
> > >
> > > Would be very grateful for some input on this.
> > >
> > > Regards
> > >
> > > Patrick McHale
> > > Powerlan USA

Reply via email to