help-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: dynamic_cast problem


From: Earl Purple
Subject: Re: dynamic_cast problem
Date: 7 Jul 2006 04:38:31 -0700
User-agent: G2/0.2

Bernd Strieder wrote:
> Looking at
>
> http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/C++-dlopen-mini-HOWTO.html
> which tries to provide a portable solution:

I think I saw that around 2 years ago. It is not even accurate. For
example this statement is false:

"Classes
Another problem with the dlopen API is the fact that it only supports
loading functions. But in C++ a library often exposes a class which you
would like to use in your program. Obviously, to use that class you
need to create an instance of it, but that cannot be easily done."

Firstly you can load objects with dlsym, in fact it is better to do so.
Casting void * to a function pointer is undefined behaviour whereas
casting it to an object is defined as long as it's a valid cast (i.e.
you are casting it to the correct type).

> You probably have a virtual base class, and you have a derived class
> being passed through base class pointers. If both classes have to be
> exposed to the executable, then they could be passed from the plugin
> independently, by factory methods of their own, and no casting would be
> necessary.

I have a generic system, thus in simple terms I have a class called
Builder which is an abstract base class, then a template we can call it
BuilderT which derives from Builder, then all classes derive from
BuilderT< T > where T is a base-class. BuilderT inherits public and
virtual from Builder. This part is not a problem.

You then have a class BuilderFactory which is abstract and derives from
DLObject and the symbols that are loaded with dlsym all derive from
BuilderFactory (and thus from DLObject.

Now the casting here works fine.

Then the loaded BuilderFactory is invoked to create its builder (just
once) and does so fine too. It is when you try to cast the Builder to
the BuilderT that the cast is not always working correctly.

The failure seems to happen when one "plugin" (shared-object library)
tries to cast a builder from another "plugin", i.e. both libraries have
been loaded with dlopen.

This happens because an object in one library needs a reference (well
shared pointer actually) with an object in the other.

> A second option might be a user-defined cast, i.e. a virtual member
> function in the base class returning a pointer to the derived class,
> returning 0 by default, overwritten in the derived class to do the
> right thing.
> Both options have the disadvantage, that those classes you want to be
> able to cast to become part of the overall plugin interface. It would
> not work, if all plugins required it.

That would be possible as the Builder interface can enforce it. It
would not apply to every abstract or base class in general because
there are no restrictions regarding them, except that the concrete
classes have to take their components as shared pointers.

How would one do this though? Because there is no such thing as a
virtual template function (and rightly so) so something like:

template < typename T >
virtual bool supportsInterface( T* & ptr );

(where T is the type you are trying to cast to and it sets ptr to this
or 0 and returns true/false)

is not possible in C++.

> A third option for verifying purposes could be a user-defined rtti
> function returning a specific id for every class.

Possible and what I might have to revert to. I think that's how COM
does it (with their horrible UUIDs thus no need to make that function
up there a template).

> Whatever, a not failing dynamic_cast has to be in the code of the plugin.

Yes. Now I call dlopen with RTLD_LAZY. Is that the correct option?
Should I use a different parameter?

> dynamic_cast is necessary in some cases, or it would not exist. Coding
> around it is about as ugly as the cast itself.

which is why I put it in the low-level library code only and business
code will not be doing any casting.

I will try a bit harder to get this to work because I don't want to
have to try my own casting system (supposedly you check then do
static_cast?)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]