Russian Qt Forum
Ноябрь 22, 2024, 02:05 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Миграция с MinGW на MSVC2015  (Прочитано 17421 раз)
Николай
Гость
« : Июнь 28, 2016, 17:06 »

Добрый день всем!
Пытаюсь перевести  проект (динамическую библиотеку) с MinGW на MSVC2015.

На MinGW никаких проблем не было.
На MCVC2015 при сборке сыпется предупреждениями и ошибками:

Цитировать
предупреждение: C4190: 'getVersion' has C-linkage specified, but returns UDT 'QString' which is incompatible with C
предупреждение: C4190: 'selectDates4Report' has C-linkage specified, but returns UDT 'QStringList' which is incompatible with C

ошибка: C2526: 'selectDepts': C linkage function cannot return C++ class 'QList<QList<QString>>'
предупреждение: C4190: 'drawGraph' has C-linkage specified, but returns UDT 'QImage' which is incompatible with C

.pro
Код:
greaterThan(QT_MAJOR_VERSION, 4) {
  QT += widgets
  DEFINES += HAVE_QT5
}
TEMPLATE =  lib
TARGET   =  rsrcs
QT += sql network
CONFIG   += shared dll plugin

DEFINES  += D_SHARED_LIB
SOURCES  =  src/rsrcs.cpp

HEADERS  =  src/rsrcs.h


DESTDIR  =  ../../core/bin/


OBJECTS_DIR = build/
MOC_DIR = build/
RCC_DIR = build/

TRANSLATIONS += ../../core/bin/l10n/rsrsc_ru.ts
message($$DEFINES)


.h
Код:

#include <QtGlobal>
#include <QtCore>
#include <QDebug>


//---minGW
/*#ifdef D_SHARED_LIB
        #define D_SHARED_LIB_EXPORT Q_DECL_EXPORT
#else
        #define D_SHARED_LIB_EXPORT Q_DECL_IMPORT

#endif
*/
//---msvc

#ifdef D_SHARED_LIB
        #define D_SHARED_LIB_EXPORT __declspec(dllexport)
#else
        #define D_SHARED_LIB_EXPORT __declspec(dllimport)
#endif


//SHARED FUNCTIONS_______________________________________________________________________
extern "C" D_SHARED_LIB_EXPORT const QString getVersion();

extern "C" D_SHARED_LIB_EXPORT const QStringList selectDates4Report(QWidget *parent);

extern "C" D_SHARED_LIB_EXPORT const QList< QList<QString> > selectDepts(const QStringList &connectionParameters, bool multiSelection, bool showDeletedItems, int id_firm, QWidget *parent, Qt::WindowState state);
extern "C" D_SHARED_LIB_EXPORT const QList< QList<QString> > selectPosts(const QStringList &connectionParameters,  bool multiSelection, bool showDeletedItems, int id_firm, int id_dept, QWidget *parent, Qt::WindowState state);
extern "C" D_SHARED_LIB_EXPORT QImage drawGraph(const QStringList &names,const QList<double> &values,int itemsLimit);




Прошу помощи. Буду рад любой полезной информации
« Последнее редактирование: Июнь 28, 2016, 17:15 от Николай » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #1 : Июнь 28, 2016, 17:39 »

extern "C" явно лишняя, так как в чистом Си отсутствуют шаблоны и классы.
MinGW игнорирует эту запись, а MSVC - нет.
Записан
Николай
Гость
« Ответ #2 : Июнь 29, 2016, 14:11 »

extern "C" явно лишняя, так как в чистом Си отсутствуют шаблоны и классы.
MinGW игнорирует эту запись, а MSVC - нет.


https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application/ru

Цитировать
QLibrary может использоваться для загрузки разделяемых библиотек в момент выполнения. В этом случае достаточно иметь доступ только к .dll, доступ к заголовкам и .lib файлу(ам) не требуется.

Следующий пример показывает, как установить библиотеку для использования с QLibrary. Для разрешения имен функций, они должны быть экспортированы из библиотеки как C функции (т.е. без искажения имени). Это означает, что функции должны быть обернуты в блок extern "C", в случае если библиотека скомпилирована компилятором C.


Или это к MSVC не относится, так это C++, а не C?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Июнь 29, 2016, 14:58 »

extern "C" нужно если Вы хотите сами находить/дергать ф-ции по имени (в примере library.resolve("createWidget1").
Обычно необходимости в этом нет. Убираете extern C и просто компилите библиотеку. Получаете (помимо dll) небольшой lib файл (фактически обертку), вот его подключаете к проекту который использует либу.

Цитировать
предупреждение: C4190: 'selectDates4Report' has C-linkage specified, but returns UDT 'QStringList' which is incompatible with C
Такие предупреждения надо все убрать, обычно они означают crash на выполнении
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #4 : Июнь 29, 2016, 16:36 »

extern "C" нужно если Вы хотите сами находить/дергать ф-ции по имени (в примере library.resolve("createWidget1").
Нет. extern "C" указывает компилятору использовать сишный манглинг имен, вместо плюсового (в котором кодируются и аргументы).
Находить и дергать можно любые экспортируемые функции, что сишные, что плюсовые.
Записан
Николай
Гость
« Ответ #5 : Июнь 29, 2016, 17:05 »

extern "C" нужно если Вы хотите сами находить/дергать ф-ции по имени (в примере library.resolve("createWidget1").
Обычно необходимости в этом нет. Убираете extern C и просто компилите библиотеку. Получаете (помимо dll) небольшой lib файл (фактически обертку), вот его подключаете к проекту который использует либу.

Цитировать
предупреждение: C4190: 'selectDates4Report' has C-linkage specified, but returns UDT 'QStringList' which is incompatible with C
Такие предупреждения надо все убрать, обычно они означают crash на выполнении

Спасибо за совет, но я использую QLibrary для загрузки этой разделяемой библиотеки вот таким образом:
Цитировать
QLibrary lib(qApp->applicationDirPath()+QDir::separator()+"rsrcs");
if(lib.load())
{
            typedef const QList <QList<QString> > (*MyClass)(const QStringList &,bool,bool,int,QWidget *,Qt::WindowState);
            MyClass myFunction = (MyClass) lib.resolve("selectDepts");
            if(myFunction)
            {...}
}

И если убрать extern "C" функция просто не вызывается, т.е.  lib.resolve("selectDepts") не находит указанную процедуру  Грустный


можно ли как-то заставить MSVC не ругаться на QList<QList<QString>> и на возврат результата формате QImage в функции drawGraph?
Цитировать
C linkage function cannot return C++ class 'QList<QList<QString>>

Цитировать
'drawGraph' has C-linkage specified, but returns UDT 'QImage' which is incompatible with C

Подскажите, как правильно писать такие вещи?
« Последнее редактирование: Июнь 29, 2016, 17:10 от Николай » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #6 : Июнь 29, 2016, 18:33 »

Эмм... для этих целей используют плагины.

Записан

ArchLinux x86_64 / Win10 64 bit
kai666_73
Крякер
****
Offline Offline

Сообщений: 319


Просмотр профиля
« Ответ #7 : Июнь 30, 2016, 01:20 »

Вах  Шокированный
Kaкие нафиг QLibrary, какие плагины?

Igors верно глаголит...

Случай простейший - есть все необходимые исходники.
Все что нужно - это собрать библиотеку с необходимыми экспортируемыми функциями и использовать эту библиотеку без всяких выкрутасов. Соответственно, все extern "С" из библиотеки надо повыпиливать, а мудренные вызывы библиотечных функций заменить просто вызовами...
« Последнее редактирование: Июнь 30, 2016, 01:29 от kai666_73 » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Июнь 30, 2016, 05:56 »

Kaкие нафиг QLibrary, какие плагины?

Все что нужно - это собрать библиотеку с необходимыми экспортируемыми функциями и использовать эту библиотеку без всяких выкрутасов.
А если реализаций этих функций несколько и для работы нужно загружать определенную, в зависимости от каких-то параметров?

Вот у ТС похоже такая ситуация (судя по первой функции getVersion). К сожалению ему нужно для msvc, а опускаться до этого нет никакого желания. Возможно, проще будет действительно реализовать это как систему плагинов, которые экспортируют единственную функцию, конструирующую объект и возвращающую указатель на него. А все эти функции будут методами.
« Последнее редактирование: Июнь 30, 2016, 06:56 от Old » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Июнь 30, 2016, 08:23 »

Цитировать
Kaкие нафиг QLibrary, какие плагины?

1. Если грузить нужно динамически либу - в этом случае лучше именно плагины.
2. Если можно не грузить при помощи QLibrary, а линковатся - в этом случае достаточно import/export без всяких extern C.

PS: Как-бы ТС упоминал только о QLibrary => 1й вариант предпочтительнее... о линковке речи не было.



« Последнее редактирование: Июнь 30, 2016, 10:50 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Николай
Гость
« Ответ #10 : Июнь 30, 2016, 08:39 »

Kaкие нафиг QLibrary, какие плагины?

Все что нужно - это собрать библиотеку с необходимыми экспортируемыми функциями и использовать эту библиотеку без всяких выкрутасов.
А если реализаций этих функций несколько и для работы нужно загружать определенную, в зависимости от каких-то параметров?

Вот у ТС похоже такая ситуация (судя по первой функции getVersion). К сожалению ему нужно для msvc, а опускаться до этого нет никакого желания. Возможно, проще будет действительно реализовать это как систему плагинов, которые экспортируют единственную функцию, конструирующую объект и возвращающую указатель на него. А все эти функции будут методами.

Именно так. Я портирую проект с Qt 4.8 на Qt 5.7. С MinGW проблем не было ни на windows, ни на linux. Но в проекте кое-где использовался QHttp, который в Qt5x выпилили, а WebEngine не поддерживается MinGW. Отсюда и необходимость перехода с MinGW на MSVC2015.
В проекте итак используется плагинная система. есть основное ядро и есть плагины. Функции данной библиотеки должны дергаться и ядром и плагинами. Поэтому и вынесены в отдельную dll. А вызывать из плагина другой плагин как-то не эстетично же).

Вот здесь описан же способ Using QLibrary to load the shared library
http://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application
и пока сидел на mingw все работало как надо. И в чем сейчас затык с mcvc2105 не могу понять  Грустный


Цитата: Old
К сожалению ему нужно для msvc, а опускаться до этого нет никакого желания
А чем плох этот C++ компилятор из Visual Studio 2015? И какие есть альтернативы тогда?
« Последнее редактирование: Июнь 30, 2016, 08:45 от Николай » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #11 : Июнь 30, 2016, 09:07 »

У нас в заголовках дллок используется такое решение:

#if defined _MSC_VER || defined __MINGW32__ || defined __MINGW64__
   #define I_FUNCTION_EXPORT __declspec(dllexport)
#elif defined __GNUC__
   #define I_FUNCTION_EXPORT __attribute__ ((visibility("default")))
#else
   #define I_FUNCTION_EXPORT
#endif

И каждый класс помечается как I_FUNCTION_EXPORT.

Но вообще  __declspec(dllexport) это грязный хак от микрософта, по хорошему компилятор должен сам понимать, что экспортировать, а что нет.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Июнь 30, 2016, 09:12 »

Спасибо за совет, но я использую QLibrary для загрузки этой разделяемой библиотеки вот таким образом:
Цитировать
QLibrary lib(qApp->applicationDirPath()+QDir::separator()+"rsrcs");
if(lib.load())
{
            typedef const QList <QList<QString> > (*MyClass)(const QStringList &,bool,bool,int,QWidget *,Qt::WindowState);
            MyClass myFunction = (MyClass) lib.resolve("selectDepts");
            if(myFunction)
            {...}
}

И если убрать extern "C" функция просто не вызывается, т.е.  lib.resolve("selectDepts") не находит указанную процедуру  Грустный
Ну хорошо, допустим надо "только так" (по имени). Тогда вместо selectDepts надо подставить "mangled" имя. Откомпилите dll (без extern C) и посмотрите список экспортируемых ф-ций напр с помощью depends.exe. Там должно быть какое-то калечное/накрученое, но содержащее selectDepts - вот его и подставьте в resolve

Это конечно коряво, но иначе надо менять вызовы чтобы не было возврата структур, напр так
Код
C++ (Qt)
extern "C" D_SHARED_LIB_EXPORT void selectDepts2(QList< QList<QString> > & outList,
const QStringList &connectionParameters,... )
{
 outList = selectDepts(connectionParameters..);
}
 
Что не смертельно (хотя и неприятно)

Подскажите, как правильно писать такие вещи?
Насколько помню, стандарт не регламентирует поведение определяемое типом линковки, т.е. MSVC имеет право на свою реализацию/правила.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #13 : Июнь 30, 2016, 09:14 »

Функции данной библиотеки должны дергаться и ядром и плагинами. Поэтому и вынесены в отдельную dll.
Тогда вы их можете оформить как экспортируемые и подключать эту библиотеку как я ядру, так и к плагинам. Никакой ручной загрузки и поиска точек входа не понадобиться.

А вызывать из плагина другой плагин как-то не эстетично же).
Посмотрите на QtCreator. Улыбающийся

А чем плох этот C++ компилятор из Visual Studio 2015? И какие есть альтернативы тогда?
Тем, что он не умеет в современный C++ и вообще кладет на стандарты.
А альтернативы те-же - MinGW или еще можно интеловский компилятор попробовать.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #14 : Июнь 30, 2016, 10:49 »

Интел дорого, МинГВ медленный и капризный.
Студия экспресс довольно быстрая и оптимирует неплохо.
И с++11 она понимает.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.08 секунд. Запросов: 22.