【问题标题】:dynamic_cast over shared libraries fail with Qt on Android compiled with clang使用clang编译的Android上的Qt在共享库上的dynamic_cast失败
【发布时间】:2019-06-22 00:46:39
【问题描述】:

使用 Qt(5.12,带有 r18b,clang),我创建了一个导出一些类的共享库。然后我创建一个程序在这些类之间做一些dynamic_cast。在带有 VS 2015 的 Windows 下,它可以完美运行(__declspec 未在下面发布)。在带有 clang 的 Android 下,dynamic_cast 失败。我可以阅读很多主题,例如:

dynamic_cast an interface from a shared library which was loaded by lt_dlopen(libtool) doesn't work

所以我尝试在我的库项目中添加一些标志,尝试了很多东西(不确定哪一个可以工作):

QMAKE_LFLAGS += -Wl,--export-dynamic
QMAKE_LFLAGS += -Wl,-E
QMAKE_LFLAGS += -Bsymbolic

但是,即使我看到链接上使用了这些标志,它仍然失败。

这是我的 MCVE:

dynamiccast_lib.pro

TARGET = dynamiccast_lib

QT -= core
QT -= gui

QMAKE_LFLAGS += -Wl,--export-dynamic
QMAKE_LFLAGS += -Wl,-E
QMAKE_LFLAGS += -Bsymbolic

TEMPLATE = lib

CONFIG += shared

SOURCES +=  \ 
C:/dev/vobs_sde/public/lib/dynamiccast_lib/src/dynamiccast_lib.cpp

HEADERS +=  \ 
C:/dev/vobs_sde/public/lib/dynamiccast_lib/ifc/dynamiccast_lib.h

INCLUDEPATH +=  \ 
C:/dev/vobs_sde/public/lib/dynamiccast_lib/ifc

dynamiccast_prg.pro

TARGET = dynamiccast_prg

QT -= core
QT -= gui

QMAKE_LFLAGS += -Wl,--export-dynamic
QMAKE_LFLAGS += -Wl,-E
QMAKE_LFLAGS += -Bsymbolic

TEMPLATE = app

SOURCES +=  \ 
C:/dev/vobs_sde/public/prg/dynamiccast_prg/src/main.cpp

INCLUDEPATH +=  \ 
C:/dev/vobs_sde/public/prg/dynamiccast_prg/inc \
C:/dev/vobs_sde/public/lib/dynamiccast_lib/ifc

LIBS += -l$$OUT_PWD/../../lib/dynamiccast_lib/libdynamiccast_lib.so
PRE_TARGETDEPS += $$OUT_PWD/../../lib/dynamiccast_lib/libdynamiccast_lib.so

dynamiccast_lib.h

#pragma once

#include <iostream>

class BaseClass
{
public:
    BaseClass()
    {
    }

    virtual void show() = 0;
};

class DerivedClass : public BaseClass
{
public:
    DerivedClass( int attr ) : attr( attr )
    {
    }

    void show() override
    {
        std::cout << attr << std::endl;
    }

private:
    int attr;
};

class DYNAMICCAST_LIB_API Helper
{
public:
    static BaseClass* CreateIntObject( int attr );
};

dynamiccast_lib.cpp

#include "dynamiccast_lib.h"

BaseClass* Helper::CreateIntObject( int attr )
{
    return new DerivedClass( attr );
}

ma​​in.cpp:

#include "dynamiccast_lib.h"
#include <iostream>

int main( int argc, char* argv[] )
{
    BaseClass* ptr = Helper::CreateIntObject(3);
    DerivedClass* casted = dynamic_cast< DerivedClass* >( ptr );
    casted->show();    
    return 0;
}

此代码崩溃,因为 casted 为 NULL。如何让这个简单的代码在 Android 下运行?

【问题讨论】:

    标签: c++ qt shared-libraries dynamic-cast


    【解决方案1】:

    经过一番调查,我可以自己解决这个问题。根本不需要添加任何链接标志。我可以通过在BaseClass 中添加一个virtual 方法并在dynamiccast_lib.cpp 中实现它来获得这个修复(让dynamic_cast 工作)。

    添加于dynamiccast_lib.h:

    virtual ~BaseClass;
    

    添加于dynamiccast_lib.cpp:

    BaseClass::~BaseClass
    {
    }
    

    这使得dynamic_cast 可以直接从程序中工作。任何virtual 函数都会解决这个问题(不仅是析构函数),但实现必须在源文件中,而不是在头文件中(否则dynamic_cast 仍然失败)。这很令人惊讶,但这是我通过测试观察到的。

    【讨论】:

    • 原因很可能是因为在windows上,dynamic_cast对类名进行了字符串比较。相比之下,在其他平台上,可以直接比较 RTTI 或 vtable 指针(并且两个不同 DLL 中名为 Foo 的两个类最终可能具有不同的 RTTI 指针,每个 dll / 可执行文件一个)
    猜你喜欢
    • 2012-12-16
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多