Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.90/40: Рейтинг темы: голосов - 40, средняя оценка - 4.90
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491

Предупреждение при создании динамической библиотеки

11.01.2021, 19:19. Показов 9192. Ответов 56
Метки c++ (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер,

У меня мало опыта создания динамических библиотек.
Я пытаюсь написать динамическую библиотеку, в качестве системы сборки использую используя CMake.

Моя динамическая библиотека задействует Eigen библиотеку и HighFive. Это хэдэр онли библиотеки (но вторая задействует HDF5 библиотеку, которая компилируется отдельно).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "../export/myclass_export.h"
#include "../core/core.h"
 
#include <Eigen/Dense>
 
#include <optional>
 
class MYCLASS_EXPORT MyClass
{
  MyClass();
 
private:
  HighFive::Group devCurveGroup;    // warning: C4251: 'MyClass::devCurveGroup': class 'HighFive::Group' needs to have dll-interface to be used by clients of class 'MyClass' 
  HighFive::DataSet devDataD;    // warning: C4251: 'MyClass::devCurveGroup': class 'HighFive::Group' needs to have dll-interface to be used by clients of class 'MyClass' 
};
Но получаю предупреждения:
warning: C4251: 'MyClass::devCurveGroup': class 'HighFive::Group' needs to have dll-interface

Я погуглил и насколько я понял, суть заключается в следующем:
внутри класса MyClass я использую шаблонные классы стандартной библиотеки (вероятно внутри HighFive::Group и HighFive:ataSet), которые я пытаюсь экспортировать (так как экспортирую весь класс MyClass ). Шаблонные классы (и функции) в неявном виде (без явной инициализации класса/функции) нельзя экспортировать, отсюда и предупреждение насколько я понимаю. И в результате, если я скомпилирую свой класс MyClass в библиотеку с этим предупреждением, то эту скомпилированную динамическую библиотеку можно использовать только приложениями, собранными моим же компилятором (у меня MSVC 2019 x64) и нельзя путать Release/Debug версии библиотеки.

Верно ли это высказывание?
Вообще я думал что ни статические, ни динамические библиотеки, собранные компилятором А, не получается использовать с компилятором Б, и нельзя смешивать релиз/дебаг версии библиотек, иначе получаешь ошибки на этапе линковки.

class_export.h генерируется с помощью CMake функции:
Code
1
2
3
4
generate_export_header(
  ${libname}
  EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/${libname}_export.h
  )
содержимое class_export.h:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef MYCLASS_EXPORT_H
#define MYCLASS_EXPORT_H
 
#ifdef MYCLASS_STATIC_DEFINE
#  define MYCLASS_EXPORT
#  define MYCLASS_NO_EXPORT
#else
#  ifndef MYCLASS_EXPORT
#    ifdef MYCLASS_EXPORTS
        /* We are building this library */
#      define MYCLASS_EXPORT __declspec(dllexport)
#    else
        /* We are using this library */
#      define MYCLASS_EXPORT __declspec(dllimport)
#    endif
#  endif
 
#  ifndef MYCLASS_NO_EXPORT
#    define MYCLASS_NO_EXPORT 
#  endif
#endif
 
#ifndef MYCLASS_DEPRECATED
#  define MYCLASS_DEPRECATED __declspec(deprecated)
#endif
 
#ifndef MYCLASS_DEPRECATED_EXPORT
#  define MYCLASS_DEPRECATED_EXPORT MYCLASS_EXPORT MYCLASS_DEPRECATED
#endif
 
#ifndef MYCLASS_DEPRECATED_NO_EXPORT
#  define MYCLASS_DEPRECATED_NO_EXPORT MYCLASS_NO_EXPORT MYCLASS_DEPRECATED
#endif
 
#if 0 /* DEFINE_NO_DEPRECATED */
#  ifndef MYCLASS_NO_DEPRECATED
#    define MYCLASS_NO_DEPRECATED
#  endif
#endif
 
#endif /* MYCLASS_EXPORT_H */
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.01.2021, 19:19
Ответы с готовыми решениями:

Вызов функции одной динамической библиотеки из другой динамической библиотеки
Добрый день! Помогите пожалуйста разобраться со следующим вопросом. Возможно ли из одной библиотеки передать параметры для...

Ошибка при подключении динамической библиотеки
Всем привет! Помогите пожалуйста разобраться со следующим: Установил библиотеку cURL, раскидав либы и длл файлы по нужным папкам....

Утечка памяти при создании динамической переменной класса
Никак не могу исправить проблему утечки памяти при создании динамической переменной класса class Ship { private: int maxHeight; ...

56
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
14.01.2021, 20:59
Студворк — интернет-сервис помощи студентам
ок, пересмотрю... там, кстати думала, что вы критиковали код оппонента... потому что читала по-диагонали... спасибо за пояснения!.. всё хочу взяться за dll, а выгоды по сравнению со статической компиляцией не вижу пока для себя, поэтому полностью ещё не нашла время проработать эту тему... как руки дойдут - обязательно вернусь к вашим примерам и пояснениям
Цитата Сообщение от DrOffset Посмотреть сообщение
которая возвращает указатель на объект
- просто под "экспортом" имела ввиду связь между внутренностями dll и клиентом - ниточку, через которую налажено использование функционала dll извне... в технологию производства "ниточек" компилятором ещё не вникала (да, и дела компилятора - пока не мои дела)
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
14.01.2021, 21:08
Цитата Сообщение от JeyCi Посмотреть сообщение
- просто под "экспортом" имела ввиду связь между внутренностями dll и клиентом - ниточку, через которую налажено использование функционала dll извне... в технологию производства "ниточек" компилятором ещё не вникала (да, и дела компилятора - пока не мои дела)
Нет в виндовских dll никаких "ниточек". Всё чисто на соглашениях
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
14.01.2021, 21:24
JeyCi, https://docs.microsoft.com/en-... w=msvc-160
0
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
15.01.2021, 12:38
ок, пусть будет импорт (со стороны клиента)...
я вот только оставлю ТСу линк, который привлёк моё внимание в связи с чисто абстрактными классами, таблицами, отмеченными выше, и __declspec(novtable) -- касается только Windows (насколько заметила бегло) - раз уж он хочет наследовать от одного класса классы, работающие с разными файлами...
Кратко суть:
Иногда бывают такие ситуации, когда таблица виртуальных классов, в принципе, не нужна. Предположим, что мы никогда не будем инстанцировать класс. Это достаточно частая ситуация в случаях абстрактных классов – известно, что если класс абстрактный, то он не может быть инстанцирован. Вообще никак.
Встаёт вопрос: если класс никогда не инстанцируется, то зачем устанавливать виртуальный табличный указатель?
Итого после внесения атрибута __declspec(novtable) --
в ассемблерном коде таблицы виртуальных методов класса A теперь нет вообще. Но виртуальный табличный указатель по-прежнему есть и по-прежнему «весит» восемь байт! Это нужно помнить, потому что…
при инициализации класса B (наследника A) - По содержимому памяти можно без труда понять, что объект класса B был сконструирован правильно, а из логики ясно, что ненужная в данном контексте операция была пропущена- т.е. инициализация указателя на виртуальную таблицу в конструкторе базового класса.
Казалось бы, пропущена всего одна операция – смысл избавляться от неё? Но если в программе тысячи и тысячи классов, унаследованные от одного и того же абстрактного класса, избавление от одной автогенерируемой команды может серьёзно повлиять на производительность. И повлияет.
0
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
16.01.2021, 00:01  [ТС]
Если экспортируемый класс содержит шаблоны методов например:
C++
1
2
3
4
5
6
7
8
9
10
class DLL_EXPORTS MyClass
{
  MyClass(){};
 
  template <typename D>
  Eigen::MatrixX<D::Scalar> getMtx(const Eigen::DenseBase<D> &M)
  {
    return M.derived();
  }
};
Возможен ли экспорт класса с помощью интерфейсов?
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
16.01.2021, 00:08
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
экспорт класса
Экспорт класса - да. Шаблон экспортироваться не будет никаким образом. В принципе можно наделать явных инстанциаций шаблона и экспортировать их. Сам шаблон на этапе исполнения не существует, нельзя экспортировать то, чего нет.
1
2 / 2 / 0
Регистрация: 08.01.2016
Сообщений: 491
16.01.2021, 14:04  [ТС]
Не могу принять решение уже несколько дней.
Вот чистый пример самого моего класса, который я хочу экспортировать в динамическую библиотеку:
заголовок:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef SURF_H
#define SURF_H
 
#include "../h5geo_export.h"
#include "../core/core.h"
 
#include <Eigen/Dense>
 
#include <optional>
 
class H5GEO_EXPORT Surf
{
private:
  explicit Surf(HighFive::Group &surfGroup);
  static bool isSurf(HighFive::Group &surfGroup);
 
public:
  static std::optional<Surf>
  create(HighFive::Group &surfGroup);
 
  bool writeData(
      const Eigen::Ref<const Eigen::MatrixXd>& M);
 
  Eigen::MatrixXd getData();
 
public:
  HighFive::Group surfGroup;
  HighFive::DataSet surfDataD;
};
 
#endif // SURF_H
реализация:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "surf.h"
 
Surf::Surf(HighFive::Group &surfGroup) :
  surfGroup(surfGroup),
  surfDataD(surfGroup.getDataSet("surf_data"))
{
 
}
 
std::optional<Surf>
Surf::create(HighFive::Group &surfGroup){
  if (isSurf(surfGroup))
    return Surf(surfGroup);
  else
    return  std::nullopt;
}
 
bool Surf::isSurf(HighFive::Group &surfGroup){
  try {
    surfGroup.getDataSet("surf_data");
  } catch (HighFive::Exception e) {
    return false;
  }
 
  return true;
}
 
bool Surf::writeData(
    const Eigen::Ref<const Eigen::MatrixXd>& M)
{
  if (M.size() == 0)
    return false;
 
  std::vector<size_t> dims = {size_t(M.cols()), size_t(M.rows())};
  try {
    surfDataD.resize(dims);
    surfDataD.write_raw(M.data());
  } catch (HighFive::Exception e) {
    return false;
  }
 
  return true;
}
 
Eigen::MatrixXd Surf::getData(){
  std::vector<size_t> dims(surfDataD.getDimensions());
  Eigen::MatrixXd M(dims[1], dims[0]);
  try {
    surfDataD.read(M.data());
  } catch (HighFive::Exception e) {
    return Eigen::MatrixXd();
  }
 
  return M;
}
Как видите, идея использовать приватный конструктор у меня задействована, и по сути std::optional<> можно заменить на умный указатель, и тогда хочется использовать подход, основанный на интерфейсах. Но я использую сторонние шаблонные библиотеки (хэдэр онли), это Eigen и HighFive (оболочка для hdf5 чистой СИ библиотеки). Становится непонятным как мне экспортировать классы этих библиотек Eigen::MatrixXd и HighFive::Group (или DataSet).

Если экспортировать мой класс Surf, то я вижу только способ использования указанных сторонних классов (Eigen::MatrixXd и HighFive::Group) только как указателей вместо объектов, но делать этого очень не хочется, так как становится очень непривычно использовать эту библиотеку, для тех, кто работает с матрицами Eigen и HighFive.

Второй вариант это забыть про бинарную совместимость.

Библиотеку эту планирую выложить в открытом доступе, с возможностью компилировать как static и shared.

Может у кого есть четкое решение по данному вопросу с учетом приведенного примера?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
16.01.2021, 14:19
Цитата Сообщение от Kerim_Geophysic Посмотреть сообщение
Библиотеку эту планирую выложить в открытом доступе, с возможностью компилировать как static и shared.
Скорее всего, твоя dll разъедется при первом же обновлении/изменении компилятора. Т.е. смысла в ней не будет никакого, можешь даже не заморачиваться. Оставь только статическую линковку.
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
16.01.2021, 14:27
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Скорее всего, твоя dll разъедется при первом же обновлении/изменении компилятора.
oleg-m1973, а поясните, пожалуйста, ваш вывод ... мне тоже хочется избегать таких неприятностей с моим кодом в общем и целом... что надо учесть, чтобы было универсально?.. или на примере кода ТСа - в чём несовершенство, чтобы не зависеть хотя бы от обновлений компилятора? (не говоря уже о смене компилятора)... и возможно ли по его задаче не зависеть от компилятора?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
16.01.2021, 14:34
Цитата Сообщение от JeyCi Посмотреть сообщение
oleg-m1973, а поясните, пожалуйста, ваш вывод ... мне тоже хочется избегать таких неприятностей с моим кодом в общем и целом... что надо учесть, чтобы было
Тебе же выше уже вроде всё написали.
Например - ты здесь используешь класс std::optional, это означает, что реализация этого класса должна быть одинаковая в exe и dll. Ты можешь это гарантировать? Вряд ли.

Добавлено через 55 секунд
А, JeyCi, извини, не посмотрел, что это ты пишешь, думал, что автор.
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
16.01.2021, 14:51
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
ты здесь используешь класс std::optional
вот это я кстати вообще не поняла - зачем ему этот optional... если делать интерфейс (абстрактный класс), то и никакие опции выбирать не надо, просто задействовать "динамическое приведение указателей родительского класса в указатели дочернего класса" (как раз для run-time'а)
C++
1
2
Parent *p = getObject(true); 
Child *ch = dynamic_cast<Child*>(p); // используем dynamic_cast для конвертации указателя класса Parent в указатель класса Child
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
16.01.2021, 14:55
Цитата Сообщение от JeyCi Посмотреть сообщение
вот это я кстати вообще не поняла - зачем ему этот optional... если делать интерфейс (абстрактный класс), то и никакие опции выбирать не надо, просто задействовать
А где-то гарантируется, что dynamic_cast работает одинаково для всех компиляторов?

Добавлено через 1 минуту
В OLE/COM для этих целей сделан IUnknown::QueryInterface, т.е. внешний модуль сам преобразовывает свои указатели.
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
16.01.2021, 14:56
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
А где-то гарантируется...
я ещё не дочитала стандарт... ...
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
16.01.2021, 14:57
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
А где-то гарантируется, что dynamic_cast работает одинаково для всех компиляторов?
Имеется ввиду, что ты можешь в visual c++ преобразовать указатель, который тебе вернул модуль, скомпилированный в gcc, при помощи dinamic_cast
0
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
16.01.2021, 14:57
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
COM - IUnknown::QueryInterface, т.е. внешний модуль сам преобразовывает свои указатели.
вот... это я ему ещё на прошлой странице советовала... - для универсальности....
спасибо за пояснения
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
16.01.2021, 15:02
Цитата Сообщение от JeyCi Посмотреть сообщение
я ещё не дочитала стандарт... ...
Я бы не стал на это закладываться. Указатели из внешних модулей лучше преобразовывать только при помощи reinterpret_cast. Соответственно, dll должна возвращать именно такие указатели
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
16.01.2021, 15:03
можно ли сказать, что универсальны могут быть только экспортированные из dll функции??
в противовес указателям
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
16.01.2021, 15:19
Хотя, я никогда не работал с классами, которые экспортируются из dll (ну, кроме OLE/COM и подобного). Поэтому не знаю современного состояния проблемы. Может там всё нормально.

Добавлено через 1 минуту
Цитата Сообщение от JeyCi Посмотреть сообщение
можно ли сказать, что универсальны могут быть только экспортированные из dll функции??
Нет, универсальны только указатели, которые корректно преобразуются при помощи reinterpret_cast. В частности, это функции.

Добавлено через 13 минут
Вообще, правильная стратегия при разработке dll, это рассчитывать на то, что твоя dll и exe, который её подключает, написаны на разных языках программирования. Либо на одном, но dll была сделана двадцать лет назад и, кроме заголовков, никаких исходников нет.
1
264 / 153 / 33
Регистрация: 29.06.2019
Сообщений: 1,554
16.01.2021, 15:49
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
универсальны только указатели, которые корректно преобразуются при помощи reinterpret_cast. В частности, это функции.
значит ему надо делать функцию, а любые классы внутри dll пусть существуют только для того, чтобы обслуживать эту экспортируемую функцию... ведь если dll уже откомпилирована будет, то - там внутри уже вроде всё настроено будет для работы экспортируемой функции и расхождения в классах, обслуживающих её (эту функцию) с подобными классами клиента, уже не будут иметь значения, - ведь внутри уже будет сплошной машинный код... я так понимаю структуру того, что он может соорудить/переделать полезного... имхо... если такой view имеет право на универсальность? (с учётом reinterpret_cast)

Добавлено через 5 минут
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В частности, это функции.
весь код на c++ - это одни сплошные функции, даже main()... классы- это лишь абстракции их обслуживающие...
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
16.01.2021, 15:57
Цитата Сообщение от JeyCi Посмотреть сообщение
весь код на c++ - это одни сплошные функции, даже main()... классы- это лишь абстракции их обслуживающие...
Это слишком широкое обобщение. Компилятор генерит довольно кода много для этих функций.
В частности, static_cast и dynamic_cast могут возвращать указатель, отличный от переданного. Не говоря о том, что dynamic_cast выполняет проверку в рантайме. В другом модуле всё это может рассчитываться по другим правилам.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.01.2021, 15:57

Синтаксическая ошибка при создании библиотеки: __declspec(dllimport)
Итак, братья-кролики , создаю я дллку с таким вот кодом , а мне ошибочку все время не понятную выбивает. Подсобите с решением. #ifndef...

Компилятор требует функцию main при создании библиотеки
Я создал проект на плюсах. В настройках проекта в Configuration Properties -&gt; General -&gt; Configuration Type выбрал Static Library (.lib) ....

Любимый Visual Studio не хочет поспособствовать мне в создании библиотеки(статической и динамической)
Уважаемые программисты, если вы дружите с этой прекрасной средой разработки, то прошу вас обосновать, как мне найти данное окно, если при...

Ошибка преобразования при сборке динамической библиотеки
При сборке программы с динамической библиотекой позднего связывания вылазит ошибка: Пробовал как-нибудь преобразовать к одному типу, но не...

Зачем при создании библиотеки создавать два файла (.h и.cpp)
Приветствую. Решил научиться писать часто используемые классы в ДЛЛ . На МСДН все понятно расписано . Однако возникли вопросы : 1.Зачем...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru