Russian Qt Forum

Qt => Вопросы новичков => Тема начата: libertas от Март 17, 2014, 22:24



Название: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 17, 2014, 22:24
Всем привет!

Хочу создать и использовать статическую библиотеку в клиенте(функции для калькулятора).

Создал в creatore статическую библиотеку, получил 4 файла:
-stat_lib.pro
-stat_lib.h
-stat_lib_global.h
-stat_lib.cpp

В stat_lib.pro добавил DESTDIR += ../lib (По заданию в этом каталоге должна стать библиотека, но у меня ничего не появилось после сборки...)

В stat_lib.h описал экспортируемые функции:
Код:
int add(int, int);

int mul(int, int);

int subtract(int, int);

int divide(int, int);

В stat_lib.cpp определил экспортируемые функции:
Код:
int add(int first_value, int second_value)
{
    return first_value + second_value;
}

int subtract(int first_value, int second_value)
{
    return first_value - second_value;
}

int mul(int first_value, int second_value)
{
    return first_value - second_value;
}

int divide (int first_value, int second_value)
{
    return first_value / second_value;
}

Далее создал клиента на базе QMainWindow:

- в mainwindow.h включил #include "stat_lib.h"
- в проекте указал путь к .h файлу - INCLUDEPATH+= ../stat_lib  и саму библиотеку LIBS+=  ../lib/libstat_lib.a

В клиенте описал функцию сложение:
Код:
void MainWindow::on_add_clicked()
{
    QString first_value = ui->first_value->text();
    QString second_value = ui->second_value->text();
    int ifirst_value = first_value.toInt();
    int isecond_value = second_value.toInt();
    int result = add(ifirst_value, isecond_value);
    ui->result->setNum(result);
}

И теперь когда запускаю run клиента получаю ошибку:
Starting D:\Temp\C++\QT_labs\Client\debug\Client.exe...
The program has unexpectedly finished.
D:\Temp\C++\QT_labs\Client\debug\Client.exe crashed

Из-за чего это может происходить?
Спасибо.

 


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 09:15
Понял, что ошибка происходит, на строчке:

Код:
int resul = add(ifirst_value, isecond_value);

Но что с ней не так?


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: Bepec от Март 18, 2014, 09:45
Половины кода нет, про файла полностью нет. Могу только протелепатировать, что у вас где-то что-то не так :D


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: OKTA от Март 18, 2014, 09:47
Наверно Боги придумали debug  ::)


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 12:51
Цитировать
Половины кода нет, про файла полностью нет.

stat_lib.pro

Код:
QT       -= gui

TARGET = stat_lib
TEMPLATE = lib

DEFINES += STAT_LIB_LIBRARY

SOURCES += stat_lib.cpp

HEADERS += stat_lib.h\
        stat_lib_global.h

unix {
    target.path = /usr/lib
    INSTALLS += target
}

DESTDIR += ../lib

client.pro

Код:
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Client
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

INCLUDEPATH += ../stat_lib

LIBS += ../lib/libstat_lib.a

stat_lib.h

Код:
#ifndef STAT_LIB_H
#define STAT_LIB_H

#include "stat_lib_global.h"

#endif // STAT_LIB_H


int add(int, int);

stat_lib_global.h
Код:
#ifndef STAT_LIB_GLOBAL_H
#define STAT_LIB_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(STAT_LIB_LIBRARY)
#  define STAT_LIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define STAT_LIBSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // STAT_LIB_GLOBAL_H

stat_lib.cpp
Код:
#include "stat_lib.h"

int add(int first_value, int second_value)
{
    return (first_value + second_value);
}

client

mainwindow.h
Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "stat_lib.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_add_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

main.cpp

Код:
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}


mainwindow.cpp

Код:
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_add_clicked()
{
    QString first_value = ui->first_value->text();
    QString second_value = ui->second_value->text();
    int ifirst_value = first_value.toInt();
    int isecond_value = second_value.toInt();
    int result = add(ifirst_value, isecond_value);
    //ui->result->setNum(result);
}


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 12:53
Код:
Наверно Боги придумали debug

В отладчик не заходит. Появляется ошибка "during startup program exited with code 0xc0000135"


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: OKTA от Март 18, 2014, 13:05
Судя по коду,  функции из библиотеки просто не экспортируются. Не хватает Q_DECL_EXPORT в заголовочнике перед int add()


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: Alex Custov от Март 18, 2014, 13:11
скинь полный архив с минимальными исходниками.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 13:17
Цитировать
скинь полный архив с минимальными исходниками

добавил во вложение.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 13:19
Цитировать
Не хватает Q_DECL_EXPORT в заголовочнике перед int add()

добавил в stat_lib.h Q_DECL_EXPORT перед  int add(int, int), пересобрал оба проекта - запускаю клиента - то же самое.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: OKTA от Март 18, 2014, 13:26
А сама Qt статически собрана?
Делаешь dll - все ок, ф-ии экспортируются, а в статике пусто. Я может конечно что-то путаю, но вроде всегда статическая сборка зависела от статической сборки Qt.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: Alex Custov от Март 18, 2014, 13:34
в исходниках не хватает формы. Вместо ручного ввода на форме я захардкодил значения:

Код
C++ (Qt)
   QString first_value = "2";
   QString second_value = "5";

Всё работает. Попробуй тоже захардкодить. Если заработало, то неправильно выполняется преобразование из QString в int.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 13:59
Цитировать
А сама Qt статически собрана?
Делаешь dll - все ок, ф-ии экспортируются, а в статике пусто. Я может конечно что-то путаю, но вроде всегда статическая сборка зависела от статической сборки Qt.

был type у библиотеки  shared library. я сейчас создал занова оба проекта, теперь у библиотеки выбрал static library.

Но все равно тоже самое. У меня в папке lib, которую я указал как DESTDIR = ../lib ничего не создается

а в .pro  у клиента я указал
 INCLUDEPATH+= ../stat_lib

LIBS+=  ../lib/libstat_lib.a

может в этом дело?


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 14:10
Такое чувство, что дело с путями

Сейчас такая структура:

проект client - QT_labs\client
проект stat_lib - QT_labs\stat_lib
библиотеки - QT_labs\lib и там есть libstat_lib.a и stat_lib.dll

В client.pro -
INCLUDEPATH+= ../stat_lib

LIBS+=  ../lib/libstat_lib.a

В stat_lib.pro -

DESTDIR = ../lib

и все равно ошибка.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: OKTA от Март 18, 2014, 14:22
Параллельный вопрос - получается достаточно одного Q_DECL_EXPORT в начале заголовочника и не обязательно его писать у каждой функции?


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: Alex Custov от Март 18, 2014, 14:31
Параллельный вопрос - получается достаточно одного Q_DECL_EXPORT в начале заголовочника и не обязательно его писать у каждой функции?

нет, это просто неправильный код. К слову, с MinGW я не видел проблем, когда Q_DECL_EXPORT не используется.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: OKTA от Март 18, 2014, 14:39
ничего не понимаю) ставишь в заголовочнике - экспортируются все, ставишь у функции - экспортируется только она.
А насчет статики? Qt не обязательно разве пересобирать?


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: Alex Custov от Март 18, 2014, 14:45
ничего не понимаю) ставишь в заголовочнике - экспортируются все, ставишь у функции - экспортируется только она.

нужно писать возле каждой функции. У автора это не используется.

А насчет статики? Qt не обязательно разве пересобирать?

Нет, а зачем? Тут не используется статическая линковка с Qt, а только со своей собственной библиотекой.

Если же автор хотел получить полностью статический бинарник, то он ошибался, и Qt действительно нужно будет пересобирать.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: OKTA от Март 18, 2014, 14:53
А если явно не экспортировать методы, разве они должны сами по себе экспортироваться?  ???


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 15:00
Q_DECL_EXPORT -на сайте qt написано, что используется для shared library -
http://qt-project.org/doc/qt-4.8/qtglobal.html#Q_DECL_EXPORT



Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 18, 2014, 15:02
Код:
А если явно не экспортировать методы, разве они должны сами по себе экспортироваться?

На сколько я успел понять, то что если указать в
LIBS в .pro клиента путь до библиотеки, то таким образом мы подключаем библиотеку.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: OKTA от Март 18, 2014, 15:34
да, верно. из-за того, что статическая библиотека всаживается прямо в приложение ничего экспортировать не нужно.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: Alex Custov от Март 18, 2014, 15:47
А если явно не экспортировать методы, разве они должны сами по себе экспортироваться?  ???

насколько я знаю, это MSVC хрень (http://msdn.microsoft.com/ru-ru/library/a90k134d.aspx), а также хрень для компиляторов, где глобальный символ нужно экспортировать. При использовании MinGW, и тем более на Linux/gcc, я не видел ошибок когда Q_DECL_EXPORT НЕ используется.


Название: Re: создание статической библиотеки и ошибка "The program has unexpectedly finished"
Отправлено: libertas от Март 20, 2014, 08:29
Разобрался я со своими ошибками. Хочу выложить сюда алгоритм создания  клиента Qt/ статической библиотеки Qt. Может быть кому-то это поможет.

Создание библиотеки в QT creator
  • New project -> Libraries -> C++ Library -> Choose; Type - Statically Linked Library; Name - static_lib.Далее все next
  • После создания проекта для библиотеки для удобства нужно отключить теневую сборку: Project ->Shadow build->false
  • В библиотеки опишем функцию сложения. Описание класса, созданное wizardом по умолчанию в файлах проекта удаляем. Он нам не пригодится.
  • В static_lib.h объявляем функцию сложения: double add(double, double); В static_lib.cpp определяем функцию сложения:
Код:
double add(double first, double second)
{
    return first + second;
}
.
  • Собираем проект.
  • Редактируем файл static_lib.pro. Для удобства определяем каталог размещения библиотеки: : DESTDIR = ../lib. Собираем проект.

Библиотека готова, теперь создаем gui-клиента на qt
  • New project -> Applications -> Qt Widgets Application-> Choose; Name - client; Далее все next
  • После создания проекта для библиотеки для удобства нужно отключить теневую сборку: Project ->Shadow build->false
  • Создадим в дизайнере в форме два QLineEdit поля ввода значений(назовем их first и second),кнопку add и поле вывода QLabel(назовем result)
  • Напишем обработчик события для кнопки add: Правой кнопкой мыши на кнопке - go to slot - Clicked. В обработчике пишем код, где вызываем нашу функцию из библиотеки:
Код:
void MainWindow::on_add_clicked()
{
    QString first = ui->first->text();
    QString second = ui->second->text();
    int ifirst = first.toInt();
    int isecond = second.toInt();
    int result = add(ifirst, isecond);
    ui->result->setNum(result);
}
  • Редактируем файл client.pro -
     
Код:
INCLUDEPATH += ../static_lib #путь к хедеру библиотеки

LIBS += ../lib/libstatic_lib.a#путь к самой библиотеке.
  • Подключаем #include "static_lib.h" в mainwindow.cpp(в коде, где будем использовать функцию библиотеки)
  • Собираем проект, запускаем - проверяем =)