通过clang编译的Android上的Qt在共享库上进行dynamic_cast失败

时间:2019-01-28 23:26:51

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

使用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 );
}

main.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下运行?

1 个答案:

答案 0 :(得分:0)

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

添加到dynamiccast_lib.h

virtual ~BaseClass;

添加到dynamiccast_lib.cpp

BaseClass::~BaseClass
{
}

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