public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* dynamic_cast and typeids on gcc 3.2
@ 2003-04-07 12:30 Sebastien Ponce
  0 siblings, 0 replies; only message in thread
From: Sebastien Ponce @ 2003-04-07 12:30 UTC (permalink / raw)
  To: gcc

Hi,

  I would like to share here my recent experience concerning the use of
gcc 3.2 in the domains of dynamic_casts and typeids. This is related to
one of the FAQ of the gcc.gnu.org web site called "dynamic_cast, throw,
typeid don't work with shared libraries". I would like now to call it 
"dynamic_cast, throw, typeid hardly work with shared libraries but if
you really need it...".

  Here is the basic situation :
  I have three main components : Main, libCreate.so, libConsume.so. The
first one is the executable, it loads dynamically (using dlopen) the two
others.
  The two libraries are sharing some abtract interface (let's call it
IHisto) by including the same IHisto.h file. This interface inherit from
a more general abstract interface called IInterface. The key point is
that Main is only aware of the existence of IInterface but doesn't know
about IHisto.
  The way the program runs is that Main first loads libCreate, calls a
function on it that creates an object implementing IHisto and returns it
as an IInterface. Then Main gives this object to libConsume that will
use it as an IHisto after having dynamic_casted it back.

  This was working fine on gcc 2.95 but as the FAQ explains, it becomes
more complicated with 3.2. It's mentionned in the FAQ that in order to
make all this work with gcc 3.2, you have to dlopen the libraries as
RTLD_GLOBAL. This is because you want the typeid symbol of IHisto to be
present at the top level in order that both libraries share it.
  Fine, this is one solution but this has a big inconvenient, which is
that you may have symbol clashes between libConsume and libCreate. The
FAQ advises to use namespaces here. Again fine in most of the cases. Now
imagine the following :
both libCreate and libConsume are linked with libc but redefine some
functions of it. Let's say _throw. Now the redefinitions are not
identical in libCreate and libConsume and each library needs its own
definition to run correctly. You can now forget about the RTLD_GLOBAL.
One has to find something else.

  What do we have left ? The only way to share a given type without
putting it at the top level is certainly to define it in yet another
library (libHisto.so) and to link this library with both libCreate and
libConsume. What I call define the type here is actually having the
typeid symbol _ZTI6IHisto defined in the library.
  Now the remaining problem is that this symbol is a weak symbol, which
means that the symbol in libHisto will actually not be used by default
since it's already defined in the parent library. Tough luck. Except...
Except if we force it not to be weak in libHisto. This works perfectly
but I found no way to achieve it in C++. I had to build the libHisto
library from assembler code like this one : 
.globl _ZTI6IHisto
_ZTI6IHisto:
        .long   _ZTVN10__cxxabiv117__class_type_infoE+8
        .string "6IHisto"

  So let me summarise what I had to do to share a type between two
dynamically loaded library under gcc 3.2 without using RTLD_GLOBAL :
   - create a new library containing basically a single symbol
   - build it from assembler code
   - link it with all library sharing the defined type

  I don't think it's so far from the optimal since one will definitely
need an extra library to handle such situations. However, I would really
like to avoid the usage on assembler here.
  Does anybody think of something simpler or more clever ?

Sebastien


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-04-07  8:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-07 12:30 dynamic_cast and typeids on gcc 3.2 Sebastien Ponce

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).