Re: Switching between interfaces without knowing derived object.

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

 



Hi all, 
 
This question pertains to use of dynamic_cast. Afaik this implementation is not defined by the C++ language standard. The gcc version i am using is 4.0.1 on Mandriva Linux release 2006. 

We have two interface classes I1 and I2 and a derived Class D implementing both of these interfaces. This is a part of the dynamically loaded library and the library-user does not know the definition of Class D. It knows only about I1 and I2. API's of this library return  pointers to interfaces, say I1 for this example. So if the user has a pointer to object of type I1 and wants to convert it to I2* dynamic_cast operator can be used(AFAIK). Note that I1 and I2 are independent, i.e I1 does not implement I2 or vice-versa. When the shared library, libtest.so, is passed as -ltest to g++, while building the user application then the dynamic_cast works as expected. 

The problem is that dynamic_cast returns NULL, when the shared library is linked and loaded at run time. A point to note here is that even though dynamic_cast fails the delete on the Interface pointer correctly calls the derived classes destructor. 

Is dynamic_cast expected to fail in this scenario? Could i do something to make dynamic_cat work for libraries linked and loaded at run time. Sample code is given below.

Thanks
-hardy


The library is built as libtest.so 
g++ -O2 -Wall -fPIC -c  testlib.cpp 
g++ -shared -o libtest.so *.o 

The application is compiled as
g++ -O2 -Wall -o test test.cpp testlib.h -ldl 


This is testlib.cpp 
#include "testlib.h" 
class Derived : public Itf1, public Itf2 
{ 
public: 
     virtual ~Derived(){} 
     void bar() { cout << "Bar" << endl; } 
     void foo() { cout << "Foo" << endl; } 
}; 

#ifdef __cplusplus 
extern "C" { 
#endif 
void* GetItf() 
{ 
     Derived* d = new Derived(); 
     return static_cast<Itf1*>(d); 
} 

#ifdef __cplusplus 
} 

#endif 
This is testlib.h 
#include <iostream> 
using namespace std; 
class Itf1 { 
public: 
     virtual ~Itf1() {} 
     virtual void foo() = 0; 
}; 

class Itf2 { 
public: 
     virtual ~Itf2() {} 
     virtual void bar() = 0; 
}; 

This is the user application test.cpp 
#include <dlfcn.h> 
#include "testlib.h" 
int main(void) 
{ 
     void *lib_handle; 
     void* (*GetInterfaceFromLib)(); 
     char *error; 
     lib_handle = dlopen("/pathtolib/libtest.so", RTLD_LAZY); 
     if (!lib_handle) 
     { 
         cout << dlerror() << endl; 
         exit(1); 
     } 
     GetInterfaceFromLib = (void*(*)())dlsym(lib_handle, "GetItf"); 
     if ((error = dlerror()) != NULL) 
     { 
         cout <<  error << endl; 
         exit(1); 
     } 
     Itf1* p = NULL; 
     void** pvoid =  (void**)(&p); 
     *pvoid = (*GetInterfaceFromLib)(); 
     p->foo(); 
     Itf2* p2 = dynamic_cast<Itf2*>(p); 
     if(p2) 
         p2->bar(); 
     delete p; 
     dlclose(lib_handle); 
     return 0; 
}  


      Yahoo! recommends that you upgrade to the new and safer Internet Explorer 8. http://downloads.yahoo.com/in/internetexplorer/


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux