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.

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?.

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?


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