Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Hellrider от Январь 26, 2013, 13:57



Название: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Hellrider от Январь 26, 2013, 13:57
Изучаю создание динамической библиотеки по книге Шлее. В библиотеке содержится одна функция:
Заголовочный файл:

Код:
#ifndef DLL_H
#define DLL_H
#include <QString>
#include "DLL__global.h"

extern "C" {
    QString oddUpper(const QString& str);
}
#endif // DLL_H
Описание:
Код:
#include "dll.h"
QString oddUpper(const QString &str){
    QString strTemp;
    for(int i = 0; i < str.length(); ++i){
        strTemp += (i % 2) ? str.at(i) : str.at(i).toUpper();
    }
    return strTemp;
}
Суть проблемы в том, что при компилировании происходит ошибка:
предупреждение: C4190: для "oddUpper" задана С-компоновка, но возвращаемый тип UDT "QString" несовместим с языком Си

Шлее пишет, что при заключении в extern "C {...} компилятор не будет прикреплять информацию о типе к символьной сигнатуре функции. Без этого спецификатора
компилятор может подставить вместо имени функции совсем другое имя, в котором будет закодирована дополнительная информация.
Подскажите как решить это дело ???





Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Old от Январь 26, 2013, 14:03
Суть проблемы в том, что при компилировании происходит ошибка:
предупреждение: C4190: для "oddUpper" задана С-компоновка, но возвращаемый тип UDT "QString" несовместим с языком Си

Шлее пишет, что при заключении в extern "C {...} компилятор не будет прикреплять информацию о типе к символьной сигнатуре функции. Без этого спецификатора
компилятор может подставить вместо имени функции совсем другое имя, в котором будет закодирована дополнительная информация.
Подскажите как решить это дело ???
Компилятор тебя предупреждает, что функцию oddUpper ты декларируешь как С-функцию, но в качестве параметра и типа возвращаемого значения указываешь классы. Эта функция oddUpper не сможет работать с объектами классов.

Либо не используй классы для этой функции, либо убери extern "C" и компилятор заманглит имя этой функции.


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Hellrider от Январь 26, 2013, 14:37
Суть проблемы в том, что при компилировании происходит ошибка:
предупреждение: C4190: для "oddUpper" задана С-компоновка, но возвращаемый тип UDT "QString" несовместим с языком Си

Шлее пишет, что при заключении в extern "C {...} компилятор не будет прикреплять информацию о типе к символьной сигнатуре функции. Без этого спецификатора
компилятор может подставить вместо имени функции совсем другое имя, в котором будет закодирована дополнительная информация.
Подскажите как решить это дело ???
Компилятор тебя предупреждает, что функцию oddUpper ты декларируешь как С-функцию, но в качестве параметра и типа возвращаемого значения указываешь классы. Эта функция oddUpper не сможет работать с объектами классов.

Либо не используй классы для этой функции, либо убери extern "C" и компилятор заманглит имя этой функции.


Я убрал  extern "C". Скомпилировал. Подключил готовый dll к приложению:

Код:
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QLabel lbl("this is example text");

    QLibrary lib("DLL_");

    typedef QString (*Fct)(const QString&);
    Fct fct = (Fct)(lib.resolve("oddUpper"));
    if(fct){
        lbl.setText(fct(lbl.text()));
    }
    lbl.show();

   
    return a.exec();
}
Библиотека подключается, но функция которая в библиотеке не выполняется. Помогите разобраться, раз Шлее вместо того что бы просвятить - запутывает новичков  ;D


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Old от Январь 26, 2013, 14:42
Библиотека подключается, но функция которая в библиотеке не выполняется. Помогите разобраться, раз Шлее вместо того что бы просвятить - запутывает новичков  ;D
Боюсь, что имя у этой функции теперь не такое простое. :)

Ладно, если хочешь иметь не мангленное имя, то возвращай extern "C" и вместо QString используй char*.


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Igors от Январь 26, 2013, 14:53
Проще всего возвратить ссылку или указатель на QString (вместо значения). А "по всем правилам" - класс QString должен быть объявлен "импортируемым" в либе и "экспортируемым" в приложении. Однако я уже успел забыть подробности, поэтому лучше сам послушаю  :)


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Hellrider от Январь 26, 2013, 14:57
Библиотека подключается, но функция которая в библиотеке не выполняется. Помогите разобраться, раз Шлее вместо того что бы просвятить - запутывает новичков  ;D
Боюсь, что имя у этой функции теперь не такое простое. :)

Ладно, если хочешь иметь не мангленное имя, то возвращай extern "C" и вместо QString используй char*.


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


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Old от Январь 26, 2013, 14:59
Ну я над этим думал, можно конечно и через char*. Но уверен, должен быть способ для изначального варианта.
Тогда не обращай внимание на варнинг. :)


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Hellrider от Январь 26, 2013, 15:38
Проще всего возвратить ссылку или указатель на QString (вместо значения). А "по всем правилам" - класс QString должен быть объявлен "импортируемым" в либе и "экспортируемым" в приложении. Однако я уже успел забыть подробности, поэтому лучше сам послушаю  :)

Тоже хочу послушать об этом  ::)


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Hellrider от Январь 28, 2013, 14:49
Неужели никто не знает как это делается правильно? Помогите. Я перелопатил инфу об этом и вообще запутался теперь  ???. Знаю точно, что нужно использовать макросы или типа того, для
импорта/експорта (в случае с виндой и компилятором msvs). Но как правильно реализовать не осиливаю.


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Bepec от Январь 28, 2013, 15:00
Кхм. Я не совсем понимайт о чем вы гаварийтен, но не это ли вы ищете?

Код:
#ifdef MYCLASS_LIB
# define MYCLASS_EXPORT Q_DECL_EXPORT
#else
# define MYCLASS_EXPORT Q_DECL_IMPORT
#endif

class MYCLASS_EXPORT QtAddonSB
{


Название: Re: extern "C" и создание динамической либы, из книги
Отправлено: Hellrider от Январь 28, 2013, 15:23
Кхм. Я не совсем понимайт о чем вы гаварийтен, но не это ли вы ищете?

Код:
#ifdef MYCLASS_LIB
# define MYCLASS_EXPORT Q_DECL_EXPORT
#else
# define MYCLASS_EXPORT Q_DECL_IMPORT
#endif

class MYCLASS_EXPORT QtAddonSB
{

Это оно, при создании библиотеки в QtCreator создается отдельный заголовочный файл и там это находится. Но как правильно реализовать...
Что-то типа
Код:
#ifndef DLL_H
#define DLL_H
#include <QString>
#include "DLL__global.h" //заголовочный файл с дефайнами

MYCLASS_EXPORT QString oddUpper(const QString& str);

#endif // DLL_H

А как в самом приложении подключать? Или это изначально не правильно? И нужно ли заключать обявление функции в extern "C"?
-----------------------------
Заключил в extern "C" и добавил макрос - заработало.


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: twp от Январь 29, 2013, 16:05
как раз по теме вопроса: How to create a library with Qt and use it in an application (http://qt-project.org/wiki/How_to_create_a_library_with_Qt_and_use_it_in_an_application)


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Hellrider от Январь 29, 2013, 22:33
как раз по теме вопроса: How to create a library with Qt and use it in an application (http://qt-project.org/wiki/How_to_create_a_library_with_Qt_and_use_it_in_an_application)

Да это я нашел еще в начале своих изысканий  ;D, там даже по-русски есть. Но голова упорно сопротивлялась понимать.


Название: Re: extern "C" и создание динамической либы, из книги Шлее
Отправлено: Bepec от Январь 30, 2013, 08:12
Что тут непонятного?
Код:
    #include <QtGui>
     
    #if defined TEST
    #define TEST_COMMON_DLLSPEC  Q_DECL_EXPORT
    #else
    #define TEST_COMMON_DLLSPEC Q_DECL_IMPORT
    #endif
     
    extern "C" TEST_COMMON_DLLSPEC QWidget* createWidget1();