Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

general XPCOM and nsCOMPtr questions..(newbie)

36 views
Skip to first unread message

Todd

unread,
Oct 20, 2006, 9:41:45 AM10/20/06
to
I'm writing some XPCOM components in C++ and I'm pretty confused about
exactly how to get some very fundamental things to work. I think I just
don't understand nsCOMPtr well enough. I've read the nsCOMPtr user manual
(http://www.mozilla.org/projects/xpcom/nsCOMPtr.html), and that was ony
partly helpful.....

At the moment, I have this specific problem. Maybe if I can see the
solution to this problem it will help me put the big picture together. I
have a couple components written in C++ with the following relationship (on
contains a list of instances of the other):

class myComponent : public myIComponent {
public:
myComponent();

private:
~myComponent();
int member_variable;
};


class myListComponent : public myIListComponent {
public:
myListComponent();

nsresult GetComponent(PRUint32 num, myIComponent **retval);
private:
~myListComponent();
nsCOMPtr<myIComponent> compList[5];
};


How would I implement GetComponent such that it returns a COPY of the
underlying myComponent from the compList? After examining the source code
for nsLocalFile, I thought I could do the following (I've omitted some error
checking to make the example simpler), but it won't compile:

myListComponent::GetComponent(PRUint32 num,myIComponent **retval)
{
*retval = new myComponent(*(compList[num]));

NS_ADDREF(*retval);
return NS_OK;
}

...but there is no copy constructer that can create the underlying
myComponent from the nsCOMPtr<myIComponent>.....what is the right way to do
this? Is there a way for me to get the underlying raw myComponent ptr such
that I can make a copy and return it?

I also tried changing the class definition for myListComponent as follows:

class myListComponent : public myIListComponent {
public:
myListComponent();

nsresult GetComponent(PRUint32 num, myIComponent **retval);
private:
~myListComponent();
myComponent compList[5];
};

...then I can write GetComponent as follows without problem:

myListComponent::GetComponent(PRUint32 num,myIComponent **retval)
{
*retval = new myComponent(compList[num]);

NS_ADDREF(*retval);
return NS_OK;
}

...I *think* that this would work OK...BUT, this won't build either because
the destructor of the myComponent objects in the list are implicitly called
by the destructor of myListComponent. Since the destructors are all
private, this won't compile. I was tempted to make myListComponent a friend
class of myComponent to make this work, but it just didn't feel right to me.
I'm convinced there is a "right" way to do what I want that I am just not
seeing.

Sorry for the long post, but I'm struggling with understanding exactly how
this stuff is supposed to work.

Todd


Boris Zbarsky

unread,
Oct 20, 2006, 10:21:49 AM10/20/06
to
Todd wrote:
> ...but there is no copy constructer that can create the underlying
> myComponent from the nsCOMPtr<myIComponent>.....

Right. The nsCOMPtr doesn't have a myComponent; it has a myIComponent. There
could be several different implementations of myIComponent, in general.

In this case, you have several options:

1) Explicitly cast comptr.get() to myComponent* if you're sure it's
a myComponent.
2) Have a clone() method on myIComponent that clones it.
3) Use nsRefPtr<myComponent> instead of nsCOMPtr<myIComponent> in
your code.

There might be other ways too, of course.

In all cases, you MUST implement a copy constructor. Not having one (as you do
now) will mean that the refcount is copied too, which is just wrong.

-Boris

Christian Biesinger

unread,
Oct 20, 2006, 11:25:00 AM10/20/06
to dev-tec...@lists.mozilla.org
Todd wrote:
> How would I implement GetComponent such that it returns a COPY of the
> underlying myComponent from the compList? After examining the source code
> for nsLocalFile, I thought I could do the following (I've omitted some error
> checking to make the example simpler), but it won't compile:

The usual way is to add a clone() method to the interface. The
implementation of that has access to the concrete class and thus has no
problems using the copy constructor to make a copy. (This is what
nsILocalFile does).

You can cast the value in an nsCOMPtr to to a concrete class, but you
need to be sure that the type stored in it is what you expect to be...

Note that another way would be to use nsRefPtr<myComponent> as the type
of your array elements instead of nsCOMPtr<myIComponent>, since that
would also ensure that you have access to the concrete type.


--
All the world's a stage,
And all the men and women merely players:
They have their exits and their entrances;
And one man in his time plays many parts, [...] --W. Shakespeare

0 new messages