From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28186 invoked by alias); 7 Apr 2003 08:41:08 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 28176 invoked from network); 7 Apr 2003 08:41:07 -0000 Received: from unknown (HELO smtp3.cern.ch) (137.138.131.164) by sources.redhat.com with SMTP; 7 Apr 2003 08:41:07 -0000 Received: from pclhcb63.cern.ch (pclhcb63.cern.ch [137.138.142.41]) by smtp3.cern.ch (8.12.1/8.12.1) with ESMTP id h378f5CA001320 for ; Mon, 7 Apr 2003 10:41:05 +0200 (MET DST) Subject: dynamic_cast and typeids on gcc 3.2 From: Sebastien Ponce To: gcc@gcc.gnu.org Content-Type: text/plain Organization: CERN Message-Id: <1049704864.17975.22.camel@PCLHCB63.cern.ch> Mime-Version: 1.0 Date: Mon, 07 Apr 2003 12:30:00 -0000 Content-Transfer-Encoding: 7bit X-SW-Source: 2003-04/txt/msg00260.txt.bz2 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