Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.79
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
#1

Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) - C++

07.02.2014, 17:22. Просмотров 3222. Ответов 46
Метки нет (Все метки)

Не, реально, зачем он?

...Друзья! Много где в инете вы найдёте как кропать dll-ки, например тут. обратите внимание на командную строку:

Bash
1
gcc -c -DBUILD_DLL dllfct.c
Да, так вот. Много где приводят примеры с использованием этго параметра, но зачем он никто толком не знает.

А вот я не поленился и скомандовал --help для каждого из экзешников лежащих в папке mingw\bin- ни для одного из экзешников такого параметра нет. То есть он просто-напросто ни одним из экзешников не используется. Вот результаты, кому интересно, в архиве.

Так зачем же нужен параметр -DBUILD_DLL? Спасибо, кто откликнется.
http://www.cyberforum.ru/cpp-beginners/thread1264563.html
0
Вложения
Тип файла: rar rez.rar (46.3 Кб, 12 просмотров)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.02.2014, 17:22
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW) (C++):

Параметр rhs, что это и для чего (конструктор-копировщик)
Вот код: #include <iostream> class jurnal { public: jurnal() { }

Для чего используется DLL?
исходники кода написанного на C++ хранятся в DLL верно?? Для чего используется...

Может ли MinGW x64 компилить приложения x32? Или нужно для этого отдельно ещё MinGW х32 качать?
Просто решил поиграться с CodeLite.

Для чего используются DLL-библиотеки?
Для чего используются DLL-библиотеки Неужели заголовочного файла мало.

Создание программы, которая будет обращаться к компилятору
Хочу написать программу, которая будет обращаться к компилятору, в нём же она...

46
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
19.02.2014, 22:31  [ТС] #41
Цитата Сообщение от DrOffset Посмотреть сообщение
Вот скажи, ты знаешь, что компилятор собирает каждый модуль отдельно, независимо? Именно поэтому у нас получаются объектные файлы на выходе cpp->obj (или o).
да
Цитата Сообщение от DrOffset Посмотреть сообщение
Понимаешь что такое компиляция?
нет
Цитата Сообщение от DrOffset Посмотреть сообщение
Понимаешь что такое связывание (линковка)?
нет
Если бы все ответы были "да", тогда и вопрос был бы плёвым.
0
DrOffset
7517 / 4513 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
19.02.2014, 23:16 #42
Цитата Сообщение от kravam Посмотреть сообщение
да
нет
нет
Если бы все ответы были "да", тогда и вопрос был бы плёвым.
Первого "да" хватит, чтобы понять почему компилятор не в состоянии узнать природу вызываемой функции.
В момент построения кода конкретного модуля у него нет информации об остальных модулях. В некоторых других языках - это не так и С++ часто за это ругают. Но эта архитектура уже существует. И мы идем от нее.

Линковщик работает потом и занимается разрешением ссылок между модулями. Вставляет сервисный код, характерный для заданной платформы. На его этапе уже можно понять что откуда вызывается, но здесь уже поздно. Ведь объектник может быть собран с хитрой оптимизацией, причем оптимизация может быть задана разная для разных объектников, просто так взять и вынуть одну инструкцию и вставить другую линкер не может. Даже без оптимизации не может. Вообще это не принципиально, я просто привел пример того, какие трудности стоят на пути реализации такой возможности в ликере.

Хотя существуют решения, которые потребуют ухода от текущей архитектуры, увеличения времени сборки.
Называется LTCG (Microsoft specific). Наверное твой вопрос разрешится, если задействовать LTCG. Но если разобраться, то это читерство, т.к. после включения LTCG obj-файл содержит уже не машинный код, а некоторое промежуточное представление, с которым может работать компилятор при последующих проходах. Это уже совсем не классический С++, хоть и может давать существенный прирост производительности.
1
Nick Alte
Эксперт С++
1646 / 1018 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
20.02.2014, 15:25 #43
Цитата Сообщение от DrOffset Посмотреть сообщение
Называется LTCG (Microsoft specific).
В GCC это называется LTO.
Цитата Сообщение от DrOffset Посмотреть сообщение
Это уже совсем не классический С++
Технические особенности работы компилятора и линковщика собственно к C++ не относятся. Так что никакой потери "классичности" нет, по этому поводу можно не беспокоиться. Как и прежде, мы имеем на входе исходные коды, а на выходе исполняемый файл или библиотеку.
0
DrOffset
7517 / 4513 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
20.02.2014, 15:32 #44
Цитата Сообщение от Nick Alte Посмотреть сообщение
В GCC это называется LTO.
Да. Появилось относительно недавно.

Цитата Сообщение от Nick Alte Посмотреть сообщение
Технические особенности работы компилятора и линковщика собственно к C++ не относятся. Так что никакой потери "классичности" нет, по этому поводу можно не беспокоиться. Как и прежде, мы имеем на входе исходные коды, а на выходе исполняемый файл или библиотеку.
Чтобы было понятно, я в этом своем утверждении исходил не из стандарта языка, а из заявления Страуструпа (если мне не изменяет память - в книге The Design and Evolution of C++), что С++ проектировался так, чтобы исключить лишние проходы компилятора и иметь максимально возможную совместимость с С, если не на уровне кода, то на уровне линковки. То есть это уже практическая сторона (вне стандарта) и взгляд Страуструпа на этот вопрос.
0
Nick Alte
Эксперт С++
1646 / 1018 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
20.02.2014, 15:44 #45
Цитата Сообщение от DrOffset Посмотреть сообщение
Да. Появилось относительно недавно.
Так ведь и у Микрософта оно не с начала времён.
Цитата Сообщение от DrOffset Посмотреть сообщение
То есть это уже практическая сторона (вне стандарта) и взгляд Страуструпа на этот вопрос.
Точнее говоря, это вопрос реализации. Но даже с учётом этого аспекта процесс всё равно не изменяется принципиально: компилятору достаётся меньше работы и он выдаёт более "сырой" промежуточный формат, линкеру приходится потрудиться больше, но по большому счёту обе фазы всё те же, всё там же.
0
DrOffset
7517 / 4513 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
20.02.2014, 15:52 #46
Да. И забыл упомянуть, что я не "вспомнил" про GCC-шный вариант потому, что он как раз не "нарушает" заявленный принцип и позволяет реализовать LTO на любом линкере, поддерживаемом GCC.
Despite the "link time" name, LTO does not need to use any special linker features. The basic mechanism needed is the detection of GIMPLE sections inside object files. This is currently implemented in collect2. Therefore, LTO will work on any linker already supported by GCC.
В отличие от варианта Microsoft.

Может ли LTO от GCC провести оптимизацию, которую хочет ТС - я не знаю. Надо проверять.

Добавлено через 6 минут
Цитата Сообщение от Nick Alte Посмотреть сообщение
Точнее говоря, это вопрос реализации. Но даже с учётом этого аспекта процесс всё равно не изменяется принципиально: компилятору достаётся меньше работы и он выдаёт более "сырой" промежуточный формат, линкеру приходится потрудиться больше, но по большому счёту обе фазы всё те же, всё там же.
На самом деле этот вопрос слабо коррелирует с изначальной темой.
Все, что ты написал - верно. Но то, что я вообще это упомянул, характеризует только мое личное мнение (которое в чем-то совпало с мнением автора языка) по поводу все большего ухода от канонов и потери и так небольшой совместимости между реализациями.
Т.к. не вижу смысла дальше это обсуждать, предлагаю вернуться к теме топика
0
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
21.02.2014, 11:08  [ТС] #47
Код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//B.cpp
#include <windows.h>
#include <stdio.h>
 
void my_func_exe ();
extern "C" __declspec(dllimport) void my_func_dll_0 ();
extern "C" void my_func_dll_1 ();
 
int main () {
 my_func_exe ();
 my_func_exe ();
 my_func_dll_0 ();
 my_func_dll_0 ();
 my_func_dll_1 ();
 my_func_dll_1 ();
 return 0;
}
Командуем:
Bash
1
2
gcc -c B.cpp
objdump -d B.o
Наблюдаем B.o
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
00000000 <_main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   e8 00 00 00 00          call   b <_main+0xb>
   b:   e8 00 00 00 00          call   10 <_main+0x10>
  10:   e8 00 00 00 00          call   15 <_main+0x15>
  15:   a1 00 00 00 00          mov    0x0,%eax
  1a:   ff d0                   call   *%eax
  1c:   a1 00 00 00 00          mov    0x0,%eax
  21:   ff d0                   call   *%eax
  23:   e8 00 00 00 00          call   28 <_main+0x28>
  28:   e8 00 00 00 00          call   2d <_main+0x2d>
  2d:   b8 00 00 00 00          mov    $0x0,%eax
  32:   c9                      leave
  33:   c3                      ret
Ну тут, собсно всё понятно. Если говорим компилятору __declspec(dllimport), то он вызывает функцию так:
Assembler
1
2
mov    eax, адрес_ячейки памяти_в_таблице_импорта // пока тут ноли
call   [eax]
В остальных случаях просто вызывает
Assembler
1
call   адрес_ячейки_памяти_в_коде_приложения //пока тут ноли
Синтаксис я переделал под masm.
Так, ну а потом линкёр заполняет таблицу импорта правильными адресами, вместо нолей подставляет нужные адреса, добавляет jmp во втором случае и всё становится круто.

Последний мой вопрос был: а почему компилятор во всех случаях, где функция вызывается из dll не пишет

mov eax, адрес_ячейки памяти_в_таблице_импорта // пока тут ноли
call [eax]

В свете последний осмыслений, этот вопрос кажется теперь глуповатым. "Потому, что компилятор не линкёр, так было задумано разработчиками."- этот ответ был бы вполне себе правомерным. Кесарю кесарево. Компилятор занимается тем, чем занимается, а линкёр адресами и различием того факта, откуда вызывается функция, не объявленная как- __declspec(dllimport). (Хотя в принципе, можно было сделать иначе, но это были бы дополнительные издержки- например, два прохода компилятора.)

Собсно, именно это и говорил DrOffset.

Для продвижения вперёд информации достаточно. А вообще по большому счёту, надо было бы знать- если компилятор лепит объектные файлы, то что такое объект в понимании компилятора? Максимально конкретно подойти к этому вопросу, и найти ответ типа:

1) Объектом в понимании компилятора является тело функции без адресов
2) и т. д.

Мысль, надеюсь понятна- что за сущности такие присутствуют в объектном файле ну и по адресам узнать. Но это отдельный разговор. Как и вопрос, возникший вследствие понимания- зачем нужны *.a файлы, если в них, кроме символов, ничего нет? Вопрос для отдельной темы, конечно. Всем спасибо.
1
21.02.2014, 11:08
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.02.2014, 11:08
Привет! Вот еще темы с решениями:

Для чего нужен с++?
Я школьник, мне 16 лет, учусь в 10 классе, планирую поступить на факультет...

Для чего нужен define?
Для чего нужен оператор define? например код #define N 20 /*...

Для чего нужен EOF?
задание такое:написать программу, печатающую все вводимые символы в верхнем...

Для чего нужен break?
для чего нужен break?


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

Или воспользуйтесь поиском по форуму:
47
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru