Динамическая трансляция по общим библиотекам завершается неудачно с Qt на Android, скомпилированным с помощью clang - PullRequest
0 голосов
/ 29 января 2019

Используя Qt (5.12, с r18b, clang), я создаю общую библиотеку, экспортирующую некоторые классы.Затем я создаю программу, делающую между этими классами dynamic_cast.Под Windows с VS 2015 он работает отлично (с __declspec, не опубликованным ниже).Под Android с лязгом dynamic_cast не удается.Я мог бы прочитать много тем, таких как:

dynamic_cast интерфейс из общей библиотеки, которая была загружена lt_dlopen (libtool) не работает

Поэтому я попытался добавитьнекоторые флаги для моего библиотечного проекта, перепробовал много вещей (не уверен, какой из них работает):

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 голосов
/ 29 января 2019

После некоторого расследования я мог бы решить эту проблему самостоятельно.Нет необходимости добавлять какой-либо флаг ссылки вообще.Я мог бы получить это исправление (работать dynamic_cast), просто добавив метод virtual в BaseClass и внедрив его в dynamiccast_lib.cpp.

Добавлено в dynamiccast_lib.h:

virtual ~BaseClass;

Добавлено в dynamiccast_lib.cpp:

BaseClass::~BaseClass
{
}

Это заставляет dynamic_cast работать прямо из программы.Любая функция virtual исправит это (не только деструктор), но реализация ДОЛЖНА быть в исходном файле, а не в заголовочном файле (в противном случае dynamic_cast по-прежнему не работает).Это удивительно, но это то, что я наблюдал при тестировании.

...