Russian Qt Forum

Компиляторы и платформы => Компиляторы => Тема начата: nvrrus от Апрель 04, 2011, 10:58



Название: Один код работет в Builder, но не работает в Qt
Отправлено: nvrrus от Апрель 04, 2011, 10:58
Здравствуйте, уважаемые форумчане! Помогите, пожалуйста разобраться с одной пробш

Проблема использования билдеровской библиотеки в Qt

В обоих случаях работаю с функциями библиотеки собранной в Builder.
Получаю интерфейс I_archSource.
Вызываю последовательно три метода, GetListOfQueries, size, Get. Каждый при отработке выводит сообщение с названием метода.

Builder:

Код:
            I_archSource *m_Src;

            const GUID xxx = {0xa167cb35, 0x2572, 0x453d, 0x876a, 0x1b4a24f7f40e};

            //CreateInstance - функция библиотеки собранной в Builder (получаем объект с интерфейсом I_archSource для работы с библиотекой)
            CreateInstance(xxx, (void**)&m_Src);
           
            I_QuerriesList* Queries;

            m_Src->GetListOfQueries((void*)getPstk(),  (void*)&getConnect(), sizeof(CONNECTKLIENT), &Queries);

            unsigned size = Queries->size();

            I_archQuery* Q = Queries->Get(0);

Все четко отрабатывает. В итоге три сообщения - GetListOfQueries, size, Get

Qt:
Код:
    I_archSource *m_Src;

    GUID xxx = {0xa167cb35, 0x2572, 0x453d, 0x876a, 0x1b4a24f7f40e};

    //Acreate_instance - функция той же библиотеки выгруженная из нее динамически (получаем объект с интерфейсом I_archSource //для работы с библиотекой)
    Acreate_instance(xxx, (void**)&m_Src);

    I_QuerriesList* Queries;

    m_Src->GetListOfQueries(NULL, NULL, 0, &Queries);

    unsigned size = Queries->size();

    I_archQuery* Q = Queries->Get(0);

Валится на последней строчке  I_archQuery* Q = Queries->Get(0);

При этом если пройти size() и встать на последнюю строчку получаю два сообщения: GetListOfQueries, Get (вместо GetListOfQueries, size)

Заранее спасибо! Буду очень признателен, если что-то подскажете.


Название: Re: Один код работет в Builder, но не работает в Qt
Отправлено: nvrrus от Апрель 04, 2011, 12:54
Нашли ошибку. Кажется она в Билдере.

Это интерфейс нашей библиотеки собранной в билдере:

Код:
class I_QuerriesList : public C_UnknownStub
{
public:
    virtual void clear() = 0;
    virtual void push_back(I_archQuery* Q) = 0;
    virtual unsigned size() = 0;
    virtual I_archQuery* Get(unsigned i) = 0;
};

class C_UnknownStub : public IUnknown
{
private:
    volatile long m_cRef;
public:
    C_UnknownStub();
    virtual~C_UnknownStub();

    virtual HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject);
    virtual ULONG __stdcall AddRef();
    virtual ULONG __stdcall Release();
};

Билдер не заносит виртуальный деструктор в таблицу виртуальных функций. А Qt заносит (что правильно).
Поэтому происходит сдвиг при вызове. Вместо  clear() вызывается push_back, вместо push_back, size(). И т.д.

Убрали виртуальный деструктор, все заработало...

Но так же нельзя, без виртуального деструктора... Подскажите, пожалуйста, может кто сталкивался с этой проблемой.


Название: Re: Один код работет в Builder, но не работает в Qt
Отправлено: lit-uriy от Апрель 04, 2011, 18:18
>>А Qt заносит
Qt - библиотека классов, она ничего не заносит. Этим занимается компилятор.

Можно попробовать поискать нужные ключи к борландовскому компиллеру, или порытся по поводу этого нюанса в тырнете, вдруг патч какой-нибудь есть.

Или рискнуть собрать вашу библиотеку не борландовским компиллером


Название: Re: Один код работет в Builder, но не работает в Qt
Отправлено: Tonal от Ноябрь 08, 2011, 18:52
Скорее всего ошибка в функции GetListOfQueries.
Либо в общих хедерах.
У багланда в реализации COM-овских классов применяется "уличная магия" - отрицательные смещения для спец. методов типа деструктора. В связи с этим могут наблюдаться разные глюки при портировании.

Советы по переносимости:
В общих хедерах могут быть только константы, фукции, структуры и интерфейсы (полностью абстрактные классы).
У общих интерфейсов не должно быть деструкторов.
Всем функциям и методам следует явно задать соглашения о вызове (calling conversion).
Передавать или возвращать структуры по значению не рекомендуется.
Передавать или возвращать float-ы и/или double нежелательно.
Выравнивание данных должно совпадать.
Освобождать память и другие ресурсы следует там же где выделяли.

Эти советы не являются абсолютными, их можно нарушать, но при этом следует хорошо понимать что происходит в каждом конкретном случае на уровне ассемблера в обоих компиляторах. :)