【发布时间】:2014-04-30 08:21:38
【问题描述】:
我在共享库创建的对象上遇到了一些dynamic_cast 的问题:
架构类似于:
class A;
class B : virtual public A; // one of the several interfaces
class C : public B; // defined only in the shared library
- 主应用程序加载共享库并请求一个新的 对象
- 共享库创建一个新的
C对象,但它返回一个dynamic_cast<A*>(pointerToCclass)因为主应用是 不知道C - 当主应用程序尝试向下转换到
B从返回的A指针失败。
我怀疑在主代码和共享代码中创建的 vtable 存在一些差异可能是原因。无论如何,最初我没有意识到这个问题,因为主应用程序
调用方法void * A::getInterface( int ifEnum ),所以共享库代码成功执行向下转换,并作为空指针返回。然后主应用程序执行 reinterpret_cast 将 void 指针绑定到所需的接口。
到目前为止,当多继承架构(当C 实现多个接口时)似乎不稳定并导致分段错误时,所有这些都正常工作。
我的嫌疑人是真的吗? 是否有更好的方法或众所周知的方法来实现类似的架构?
谢谢
我附上了一些我的真实应用程序的简化代码以及主要参与者。 首先是通用定义:
class A
{
public:
typedef A* (*getAobject_fn)(void);
static A * Load( char * filename ) {
void * objhlib = dlopen( filename, RTLD_NOW );
getAobject_fn fp = (getAobject_fn) dlsym( objhlib, "getAobject" );
return fp();
}
virtual A * Create() = 0;
virtual void * getInterface( int ifEnum ) = 0;
};
class B1 : virtual public A {
public:
// some inline or pure virtual functions here
};
class B2 : virtual public A {
public:
// some other inline or pure virtual functions here
};
共享库的头文件(实际上C类对主应用程序是不可见的,因为.so是在运行时加载的,而.h不包含在主程序中):
class C : public B1, public B2
{
public:
A * Create() { return new C; }
void * getInterface( int ifEnum ) {
if( ifEnum==INTERFACE_ID_B1 )
return dynamic_cast<B1*>(this);
if( ifEnum==INTERFACE_ID_B2 )
return dynamic_cast<B2*>(this);
return 0;
}
};
extern "C" { A * getAobject(); } // probably useless
在共享库的正文中:
C obj;
A * getAobject() { return dynamic_cast<A*>(&obj); } // equivalent to return &obj;
最后,在主应用程序中:
// In the Init procedure
A * p = A::Load( "foo.so" );
A * pBobj = p->Create(); // pBobj is kept for the entire lifetime
B1 * b1 = reinterpret_cast<B1*>(pBobj->getInterface( INTERFACE_ID_B1 ));
B2 * b2 = reinterpret_cast<B2*>(pBobj->getInterface( INTERFACE_ID_B2 ));
// NOTE:
// b1 = dynamic_cast<B1*>(pBobj) and
// b2 = dynamic_cast<B2*>(pBobj)
// will fail
【问题讨论】:
-
为什么会有从 C 到 A 的不必要的动态转换?
-
@DieterLücking 动态转换是隐式的,但(我认为)始终是动态转换,所以我宁愿不要省略它。
-
将指针转换的精确序列显示,包括隐式和显式,作为代码(不是散布在问题中的口头描述)。
-
@n.m.是的。这里至少可能涉及两个问题,一个是纯粹的 g++/gcc,另一个是 C++。如果不确切知道他在做什么,很难说哪个有问题(但坦率地说,在他的情况下,我会同时解决这两个问题)。
标签: c++ inheritance gcc shared-libraries