On Tuesday 04 November 2008, Eric Gorr wrote: > Ok...this seems to be treading into some really esoteric areas of c++. > I will do my best to explain this issue, but I don't fully understand > what is happening myself. I am hoping that the problem comes down to > standard c++ stuff and is not specific to Mac OS X compiler&linker. > > I have put together a simple test project which can be found at: > > http://ericgorr.net/LibraryLoading.zip > > which demonstrates the problem. > > In Shared.h, there are the definitions of two purely virtual classes - > A & B. B is a subclass of A. > > In LibraryA, there is a implementation of class B called BImp. There > is a function called GetA which returns a pointer to an instance of > BImp and returns an A*. > > In LibraryB, there is a function called test. This function takes a > void *, which will end up being a function pointer to the GetA > function from LibraryA. > > The problem comes in the test function with the line: > > B* myB = dynamic_cast<B*> (myA); > > The dynamic_cast fails and myB is assigned NULL. This _should not_ > fail because myA is an instance of class B. > > However, I can make this dynamic_cast succeed, if in main.cp, which is > a part of the Application target, I set: > > #define CASE_A 1 > > which allows > > A *myA = functionPtr(); > B *myB = dynamic_cast<B*> (myA); > > to be executed before the test function from LibraryB is called. > > Any idea why this allows it to work? > Any idea why it is failing in the first place? > > In main.cp, there are two #define's. > > #define CASE_A 0 > #define CASE_B 0 > > If both are set to zero, it will crash. This is simplest crashing > case. > If CASE_A is 1, it will work. Any idea why? > If CASE_B is 1, it will crash and this is the case closest to the real > case I am working with. Does this[1] help in any way? [1] http://gcc.gnu.org/ml/gcc-help/2008-09/msg00173.html > Since I started composing this message, I've been looking into the > issue a bit more and thought that if it were possible to make the > destructors pure virtual functions as well, then that would solve the > problem. > > Googling for "pure virtual destructors c++", I came across: > > http://www.linuxtopia.org/online_books/programming_books/thinking_in_... > > While it seems strange, apparently this is allowed in C++. > > So, if I changed Shared.h to look like: > > ***** > ***** > #define VISIBLE __attribute__ ((visibility("default"))) > > class VISIBLE A > { > public: > virtual ~A( void ) = 0; > virtual void Func( void ) = 0; > }; > > A::~A() {} > > class VISIBLE B : public A > { > public: > virtual ~B( void ) = 0; > virtual void Func1( void ) = 0; > }; > > B::~B() {} > > extern "C" VISIBLE A *GetA( void ); > ***** > ***** > > everything worked in all three cases. > > Any comments on this solution? Any reason why this wouldn't be > perfectly valid? > > Any thoughts or comments would be appreciated. -- Mihai Donțu unices.bitdefender.com