быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
||||||
1 | ||||||
Создание *.dll: для чего нужен компилятору параметр -DBUILD_DLL? (использую MinGW)07.02.2014, 17:22. Показов 8353. Ответов 46
Метки нет (Все метки)
Не, реально, зачем он?
...Друзья! Много где в инете вы найдёте как кропать dll-ки, например тут. обратите внимание на командную строку:
А вот я не поленился и скомандовал --help для каждого из экзешников лежащих в папке mingw\bin- ни для одного из экзешников такого параметра нет. То есть он просто-напросто ни одним из экзешников не используется. Вот результаты, кому интересно, в архиве. Так зачем же нужен параметр -DBUILD_DLL? Спасибо, кто откликнется.
0
|
07.02.2014, 17:22 | |
Ответы с готовыми решениями:
46
AddItem и TObject. Для чего нужен второй параметр в приведенном коде Подскажите для чего нужен WdfCoInstallerXXXX.dll Создание и использование dll- Для чего dllimport? Нужно найти путь к компилятору MinGW в QT Creator |
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
||||||
07.02.2014, 19:04 [ТС] | 2 | |||||
Блин, тихий ужас. Оказывается, -DBUILD_DLL это -D BUILD_DLL! То есть то же самое, что
0
|
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
07.02.2014, 20:42 | 3 |
Потому что ленивые программисты используют один и тот же заголовок и для построения самой DLL, где содержащиеся в ней функции описаны как экспортируемые (со спецификатором __declspec(dllexport) в случае Visual Studio), и для использующих ту DLL программ, где их описывают уже как импортируемые, с модификатором __declspec(dllimport). Переключение как раз осуществляется проверкой макроса BUILD_DLL. Менять исходный код, добавляя-убирая этот макрос в зависимости от того, что мы собираем, неудобно. А удобно привязывать этот макрос к проекту, добавляя его в параметры компилятора, а лучше в свойства проекта в IDE, откуда он всё равно попадёт в командную строку.
2
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|
07.02.2014, 21:00 [ТС] | 4 |
Ну я так понял, в зависимости от параметра командной строки __declspec(dllexport) может поменяться на __declspec(dllimport) и наоборот. Это, наверное, удобно. Только вот я не понял, для чего мне нужно сообщать компилятору, чтобы, например функция foo экспортируется (то есть для чего, к примеру применять __declspec(dllexport)).
...Итак, я написал *.dll, определил в ней функцию foo и тело, что очень важно. Предполагаю, что функция из этой dll-ки будет экспортироваться. Теперь мне надо позаботиться об имени этой функции (модификаторы __cdecl, __stdcall и Extern "C") а также создать файл *.a, чтобы слинковать эту dll-ку с экзешником, из которого будет вызываться foo. И всё это БЕЗ __declspec(dllexport). То есть не пойму, зачем этот модификатор нужен.
0
|
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
07.02.2014, 21:45 | 5 |
А что делает файл *.a? Он всего лишь загружает DLL и вынимает из неё адреса функций, на которые и перекидывает вызовы. Это же можно делать и вручную, через LoadLibrary / GetProcAddress, без статических библиотек.
А чтобы вынуть из DLL адрес функции по её имени, необходимо, чтобы в DLL содержалась таблица имён и адресов экспортируемых функций. А чтобы компилятор знал, что в эту таблицу запихать, и нужна пометка __declspec(dllexport). Этот модификатор - единственная вещь, которая действительно необходима для экспорта функций из DLL, а остальные перечисленные вещи нужны только для согласования и/или удобства.
1
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
||||||
07.02.2014, 22:30 [ТС] | 6 | |||||
0
|
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
08.02.2014, 09:15 | 7 |
Да, об этом. Там в примере не хватает ещё вызова tstfunc для полноты картины.
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
||||||||||||||||||||||||||
08.02.2014, 22:19 [ТС] | 8 | |||||||||||||||||||||||||
Эх, нехороший я человек. Так всё складывалось в стройную картину, а тут я залез со своим нытьём.
Не по теме: Кстати, в разделе Java это называется хамством. код dll-ки
0
|
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
10.02.2014, 18:19 | 9 |
Умный, хорошо выдрессированный компилятор, который в определённых случаях сам умеет догадываться, какие функции надо экспортировать - это хорошо и полезно. Но не каждый компилятор так хорошо выдрессирован, а в ряде случаев (обычно, при создании реальных DLL, в которых не каждую функцию надо экспортировать) даже с дрессированным компилятором лучше всё же вручную указывать, кто идёт на экспорт.
Для чистоты эксперимента - а что будет, если в этом примере добавить ещё одну функцию, уже со спецификатором экспорта? Будут ли экспортироваться обе?
1
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
||||||||||||||||||||||||||
10.02.2014, 19:05 [ТС] | 10 | |||||||||||||||||||||||||
влияет на запихивание в таблицу экспорта? В смысле не куда-то там, а в определённой место, называемое таблицей экспорта?
+++++++++++++++++++++++++++++++++++++++++++++++++++++ экзешник
dll-ка
Для настоящего случая, компилятор мог быть и поумнее- если есть две или больше АВТОНОМНЫХ функций, то опять, на кой они нужны, как не на экспорт? Но он, видать, считает, что одна может вызываться из другой и тем самым не идти на экспорт, (поэтому на экспорт отправляет ту, которая __declspec(dllexport)) На месте компилятора я бы так и думал. Хотя анализ кода доказывает обратное. Но без претензий. Главное, что разобрались. Но вернёмся к нашим баранам. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Итак, необходимость явно указывать __declspec(dllexport) несомненна. Изначально вопрос стоял так- мы либо указываем __declspec(dllexport) (директивой компилятора -DBUILD_DLL), либо указываем- внимание, в том же самом месте __declspec(dllimport):
0
|
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
10.02.2014, 20:43 | 11 |
Сырцу второй раз указывать экспортность уже необязательно, достаточно того, что она объявлена в заголовке (разумеется, заголовок должен включаться в сырцы A.DLL). Там обычно и не указывают. Список экспортируемых функций выносят в A.H, который в проекте A служит списком экспортируемых функций.
Директива импорта предназначена для другого проекта B.EXE, который нашу A.DLL использует. Как использует? Подключает implib A.lib или A.a, который содержит одноимённые с экспортными функции, состоящие из простого перекидывания вызова на нужный адрес в DLL. При инициализации приложения implib загружает DLL и вынимает оттуда адреса. Тот же самый заголовочный файл A.H, который мы использовали при компиляции A.DLL, здесь работает у нас как объявление прототипов импортируемых функций. Из-за отсутствия ключа BUILD_DLL в настройках проекта B заголовок A.H подставляет директиву импорта в их описание. Благодаря тому, что мы в обоих случаях используем один и тот же заголовочный файл A.H, мы страхуемся от ошибок в объявлениях функций и необходимости вручную вести заголовок с импортируемыми функциями.
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|
11.02.2014, 07:46 [ТС] | 12 |
Второй абзац, честно говоря, не понял. Нельзя ли какой-нибудь маленький примерчик ПОЛЕЗНОГО применения __declspec(dllimport)? Для начала понять хотя бы, что даёт сей модификатор, а потом вернуться к ключу BUILD_DLL.
0
|
Jupiter
|
11.02.2014, 14:47
#13
|
0
|
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
11.02.2014, 15:12 | 14 |
Для функций он ничего принципиального не даёт, кроме разве что подсказок оптимизатору. И программисту. Впрочем, при импорте переменных из DLL он уже необходим. Само собой, этот модификатор имеет смысл только в контексте использования implib.
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|
11.02.2014, 15:21 [ТС] | 15 |
implib это что такое? НУ то есть я понимаю, что это импорт библиотек, но это программа или что?
0
|
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
11.02.2014, 21:36 | 16 |
Это библиотека импорта: та статическая библиотека, которая генерируется вместе с DLL. Она содержит в себе функции, совпадающие по именам с функциями DLL, которые просто перебрасывают вызовы в DLL. Она же содержит код, который при загрузке приложения загружает DLL и читает оттуда адреса всех функций, а при завершении приложения выгружает DLL.
Всё это можно проделывать и вручную, без implib, но с ней, понятное дело, удобнее.
1
|
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,285
|
||||||
16.02.2014, 15:05 | 17 | |||||
Сообщение было отмечено kravam как решение
Решение
Тут подробно написано.
Да BUILD_DLL не ключ, а макрос. -D - это ключ. Вот пример:
1
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|||||||||||||||||||||
17.02.2014, 20:40 [ТС] | 18 | ||||||||||||||||||||
На счёт __declspec(dllimport)- небольшой тык скыть эксперимент с отладчиком, показал, что всё так.
Не по теме: Кстати, что характерно, все экзешники, в которых я ковырялся в своей жизни, были написаны без этого модификатора- оно и понятно, ведь предполагается, что экзешники могут быть запущены на разных осях, с разными адресами API-функций и последнее слово в нахождении их адреса за загрузчиком. А теперь, когда мы так успешно выяснили, зачем всё это нужно по отдельности, возвращаемся к нашему вопросу- на фига такой вот монстр?
0
|
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,285
|
|
17.02.2014, 23:57 | 19 |
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|||||||||||
18.02.2014, 10:17 [ТС] | 20 | ||||||||||
DrOffset, опять вы думаете обо мне плохо. Там именно то и написано, зачем нужен модификатор
0
|
18.02.2014, 10:17 | |
18.02.2014, 10:17 | |
Помогаю со студенческими работами здесь
20
Нужен glaux для mingw Подлючение библиотеки sfml 2.0 sjlj к дефолтному компилятору mingw sjlj code::blocks 13.12 x32 Для чего нужен Seed() и для чего его override? MinGW - скомпилированная программа требует наличия libstdc++-6.dll и libgcc_s_seh-1.dll Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |