Как скомпилировать dll gcc

Обновлено: 07.07.2024

GСС - это свободно доступный оптимизирующий компилятор для языков C, C++.

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

Файлы с расширением .cc или .C рассматриваются, как файлы на языке C++, файлы с расширением .c как программы на языке C, а файлы c расширением .o считаются объектными.

Чтобы откомпилировать исходный код C++, находящийся в файле F.cc, и создать объектный файл F.o, необходимо выполнить команду:

Опция –c означает «только компиляция».

Чтобы скомпоновать один или несколько объектных файлов, полученных из исходного кода - F1.o, F2.o, . - в единый исполняемый файл F, необходимо ввести команду:

Опция -o задает имя исполняемого файла.

Можно совместить два этапа обработки - компиляцию и компоновку - в один общий этап с помощью команды:

<compile-and-link –options> - возможные дополнительные опции компиляции и компоновки. Опция –lg++ указывает на необходимость подключить стандартную библиотеку языка С++, <other-libraries> - возможные дополнительные библиотеки.
После компоновки будет создан исполняемый файл F, который можно запустить с помощью команды

<arguments> - список аргументов командной строки Вашей программы.
В процессе компоновки очень часто приходится использовать библиотеки. Библиотекой называют набор объектных файлов, сгруппированных в единый файл и проиндексированных. Когда команда компоновки обнаруживает некоторую библиотеку в списке объектных файлов для компоновки, она проверяет, содержат ли уже скомпонованные объектные файлы вызовы для функций, определенных в одном из файлов библиотек. Если такие функции найдены, соответствующие вызовы связываются с кодом объектного файла из библиотеки. Библиотеки могут быть подключены с помощью опции вида -lname . В этом случае в стандартных каталогах, таких как /lib , /usr/lib, /usr/local/lib будет проведен поиск библиотеки в файле с именем libname.a. Библиотеки должны быть перечислены после исходных или объектных файлов, содержащих вызовы к соответствующим функциям.

Опции компиляции

Среди множества опций компиляции и компоновки наиболее часто употребляются следующие:

В данной статье будет написано как пользоваться компилятором GCC и вспомогательными программами. Эта статья будет полезна для тех, кто только начал изучать С/С++, и не знает на чем и как компилировать свои первые программы, а также всем желающим научиться пользоваться этим компилятором.

2. Руководство

2.1. Установка MinGW на Windows.


2.2. Прописывание пути к MinGW в Windows.

Прописывание путей необходимо для того, чтобы для запуска компилятора не приходилось каждый раз писать полный путь к нему. Зайдите в Панель инструментов => Система => Дополнительно => Переменные среды. К переменной Path, через знак "точка с запятой" добавьте путь к папке /MinGW/bin.

2.3. Компиляция в Windows`е

1) Откройте консоль Пуск=> Выполнить=> cmd.
2) Перейдите в папку с исходником командой cd путь_к_папке_с_исходником например:

3) Если исходники вашей программы состоят из одного файла, то команда компиляции будет выглядеть так:
g++ исходный_файл
Например:
В результате выполнения этой команды в папке с исходником окажется откомпилированная программа.
4) Если исходники вашей программы состоят из нескольких файлов, то можно написать их имена через пробел:
g++ первый_исходный_файл второй_исходный_файл
Например:
5) Если проект состоит из большого числа исходных файлов, то скомпилировать их всех можно командой:
В данной папке все исходные файлы будут скомпилированы в одну программу.
6) Если вы не хотите каждый раз возится с консолью, можете создать *.bat файл и записать в него все необходимые команды. Делается это так: создаете текстовой документ, открываете его с блокнотом и записываете в него необходимые команды, примерно так:

2.5. Уменьшение размера исполняемого файла.
Удаление отладочной информации позволяет уменьшить размер испольняемого файла. Команда выглядит так:
strip имя_исполняемого_файла
Например:

Компиляция Objective-C в GCC
Пытаюсь выполнить компияцию кода Objective-C с помощью GCC на Windows. Для этого: 1. Установил.

Компиляция GCC в Windows
У меня в виндусе GCC для виндуса (портированный) Я хочю на нем (5,1) скомпилировать сам.

GCC:Компиляция в формат elf под Windows
Можно ли при помощи gcc создать в Windows исполняемый файл в формате elf? Если можно, то как?

gcc компиляция
Проблема возникла при компиляции проекта code::block. При build and run все работает, в папке bin.

Некоторые поправки и добавления по пунктам:

2.1 В данный момент, самая актуальная версия MinGW находится в составе MSYS2. Краткая инструкция по установке и настройке находится на главной (той же) странице официального сайта.

2.5 Параметр -s (или --strip-all ) позволяет максимально уменьшить размер исполняемого файла, удалив из него всю информацию о символах и релокации.

Компиляция gcc
Подскажите как в VS скомпилировать программу с помощью компилятора gcc

Компиляция (gcc)
Добрый вечер! После компиляции текстовый файл становится вдруг двоичным, как следствие его.

Компиляция бинарника на gcc
Задача: нужно скомпилировать сырой бинарник на gcc. Он будет грузиться по адресу 0x10000 и туда же.

Компиляция проекта в gcc
Здравствуйте, форумчане! Прошу помочь разобраться! Есть программа, представленная в 3х файлах. В.

Передо мной возникла задача написать загрузчик библиотек, имеющий возможность предоставить какие-то интерфейсные функции внешней динамической библиотеке. Решение должно быть максимально кроссплатформенно (как минимум, работать на Linux и Windows). Загружаться должны библиотеки, написанные на различных языках программирования, поддерживающих создание динамических библиотек. В качестве примера были выбраны языки C и Pascal.

Решение

Основной загрузчик библиотек написан на языке C. Для того, чтобы загружаемые библиотеки имели возможность использовать функции основной программы, основная программа разделена на 2 части: на основной и подгружаемый модули. Основной модуль нужен просто для запуска программы, подгружаемый модуль — это также динамическая библиотека, связываемая с основным модулем во время его запуска. В качестве компиляторов были выбраны gcc (MinGW для Windows) и fpc.
Здесь будет приведён упрощённый пример программы, позволяющий разобраться в данном вопросе и учить первокурсников писать модули к своей программе (в школе часто преподают именно Pascal).

Загрузчик библиотек

Главный файл загрузчика библиотек выглядит очень просто:
main.c


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

loader.c
Заголовочные файлы

Это всё была реализация, а теперь заголовочные файлы.
Вот интерфейс модуля, загружающего динамические библиотеки, для основного модуля:
loader.h


Вот интерфейс загрузчика для загружаемых им динамических библиотек (перечень функций, которые динамические библиотеки могут использовать в основной программе):

functions.h

Как видно, здесь всего одна функция printString для примера.

Компиляция загрузчика

Пример недистрибутивной компиляции (в случае Windows в опции компилятора просто нужно добавить -DWIN32):

Дистрибутивная компиляция от недистрибутивной отличается тем, что в дистрибутивном случае динамические библиотеки ищутся в /usr/lib и имеют вид lib$(NAME).so.$(VERSION), в случае недистрибутивной компиляции они называются lib$(NAME).so, а ищутся в каталоге запуска программы.

Теперь посмотрим, что у нас получилось после компиляции:

Тут видим, что функции, отмечаемые как U ищутся во внешних динамических библиотеках, а функции, отмечаемые как T предоставляются модулем. Это бинарный интерфейс программы (ABI).

Динамические библиотеки


Теперь приступим к описанию самих динамических библиотек.
Библиотека на языке C

Здесь везде окружение extern «C» <> нужно для того, чтобы нашу программу можно было компилировать при помощи C++-компилятора, такого, как g++. Просто в C++ можно объявлять функции с одним и тем же именем, но с разной сигнатурой, соответственно в этом случае используется так называемая декорация имён функций, то есть сигнатура функций записывается в ABI. Окружение extern «C» <> нужно для того, чтобы не использовалась эта декорация (тем более, что эта декорация зависит от используемого компилятора).

Компиляция

Если мы уберём в нашем модуле окружение extern «C» <> и скомпилируем при помощи g++ вместо gcc, то увидим следующее:

То есть, как и ожидалось, ABI библиотеки изменился, теперь наш загрузчик не сможет увидеть функцию run в этой библиотеке:

Библиотека на языке Pascal

Как мы увидели выше, для того, чтобы наш загрузчик видел функции в динамических библиотеках, созданных компилятором C++, пришлось дополнять наш код вставками extern «C» <>, это притом, что C/C++-компиляторы и языки родственные. Что уж говорить про компилятор FreePascal совершенно другого языка — Pascal? Естественно, что и тут без дополнительных телодвижений не обойтись.

Для начала нам нужно научиться использовать экспортированные в C функции для динамических библиотек. Вот пример аналогичного C/C++ заголовочного файла на языке Pascal:

func.pas


Вот пример самого модуля на языке Pascal:

modul.pas
Компиляция

Смотрим ABI получившейся библиотеки:

Как видим, ничего лишнего, однако настораживает предупреждение ld во время компиляции. Находим в гугле возможную причину предупреждения, это связано с компиляцией без PIC (Position Independent Code — код не привязан к физическому адресу), однако в man fpc находим, что наша опция -Cg должна генерировать PIC-код, что само по себе странно, видимо fpc не выполняет своих обещаний, либо я делаю что-то не так.

Теперь попробуем убрать в нашем заголовочном файле кусок name 'printString' и посмотрим, что выдаст компилятор теперь:

Как видно, декорация в FreePascal совсем другого рода, чем в g++ и тоже присутствует.
При запуске с этим модулем получаем:

А с правильным модулем получаем:

Вот и всё, своей задачи — использование динамических библиотек, написанных на различных языках — мы достигли, и наш код работает как под Linux, так и под Windows (у самого Mac'а нет, поэтому не смотрел, как там с этим). Кроме того, загруженные библиотеки имеют возможность использовать предоставляемые в основной программе функции для взаимодействия с ней (то есть являются плагинами основной программы).

Сам загрузчик может выполняться в отдельном процессе, чтобы эти плагины не смогли сделать ничего лишнего с основной программой. Соответственно, основная программа может быть написана на любом другом удобном языке программирования (например, на Java или на том же C++).

Мне было интересно, как мне скомпилировать DLL с gcc? Ну, я использую порт windows gcc. Как только я скомпилирую DLL, содержащую мои классы и функции, как мне связать с ней мою программу? Как использовать классы и функции в DLL? Может ли функция вызова DLL из программы связываться с ней? Если я создаю объект класса <. >; в DLL, тогда, когда DLL загружается программой, объект будет доступен для программы? Заранее спасибо, мне действительно нужно знать, как работать с DLL на С++, прежде чем я смогу продолжить этот проект.

"Можете ли вы добавить более подробную информацию о том, почему вы хотите, чтобы DLL вызывала функции в основной программе?"

Я думал, что вид диаграммы объяснил это. программа, использующая DLL, передает кусок кода в DLL, который анализирует код, и если вызовы функций найдены в указанном коде, тогда соответствующие функции в DLL вызываются. например, если я передал "a = sqrt (100)", то функция парсера DLL найдет вызов функции для sqrt(), а внутри DLL будет соответствующая функция sqrt(), которая будет вычислять квадратный корень аргумента, переданного ему, а затем он примет возвращаемое значение из этой функции и поместит его в переменную a. точно так же, как любая другая программа, но если соответствующий обработчик для функции sqrt() не найден в пределах DLL (там будет список поддерживаемых изначально функций), тогда он будет вызывать аналогичную функцию, которая будет находиться внутри программы, используя DLL, чтобы узнать, есть ли какие-то пользовательские функции этим именем.

Итак, скажем, вы загрузили DLL в программу, предоставляя вашей программе возможность интерпретировать сценарии этого конкретного языка, программа могла вызвать библиотеки DLL для обработки отдельных строк кода или передать им имена файлов сценариев для обработки. но если вы хотите добавить команду в script, которая подходит для вашей программы, вы можете сказать, что в DLL необходимо указать логическое значение, указывающее, что вы добавляете функции на свой язык, а затем создаете функцию в своем коде, которая список функций, которые вы добавляете (DLL будет вызывать его с именем функции, которую она хочет, если эта функция является определяемой пользователем, содержащейся в вашем коде, функция будет вызывать соответствующую функцию с аргументом, переданным ей DLL, вернуть возвращаемое значение пользовательской функции обратно в DLL, а если оно не существует, оно вернет код ошибки или NULL или что-то еще). Я начинаю видеть, что мне придется найти другой способ обойти это, чтобы вызовы функций проходили только в одну сторону.

ОТВЕТЫ

Ответ 1

Эта ссылка объясняет, как сделать это основным способом.

В представлении большого изображения, когда вы делаете dll, вы создаете библиотеку, которая загружается во время выполнения. Он содержит несколько символов, которые экспортируются. Эти символы обычно относятся к методам или функциям, плюс компилятор/компоновщик goo.

Когда вы обычно создаете статическую библиотеку, существует минимум goo, и компоновщик тянет код, который ему нужен, и переупаковывает его для вас в вашем исполняемом файле.

В dll вы фактически получаете два конечных продукта (три действительно - просто подождите): dll и заглушка. Штук - это статическая библиотека, которая выглядит точно так же, как ваша обычная статическая библиотека, за исключением того, что вместо выполнения вашего кода каждый заглушка обычно является инструкцией перехода к общей процедуре. Обычная подпрограмма загружает вашу DLL, получает адрес подпрограммы, которую вы хотите вызвать, затем добавляет исходную инструкцию перехода, чтобы вернуться туда, и когда вы ее снова вызовете, вы попадете в свою DLL.

Третий конечный продукт - это обычно заголовочный файл, в котором рассказывается о типах данных в вашей библиотеке.

Итак, ваши шаги: создайте заголовки и код, создайте dll, создайте библиотеку заглушек из заголовков/кода/некоторого списка экспортируемых функций. Конец кода будет связан с библиотекой-заглушкой, которая будет загружать DLL и фиксировать таблицу перехода.

Теперь о вашей основной проблеме: как написать расширяемый код в dll? Существует несколько возможных способов - типичным способом является определение чистого абстрактного класса (aka interface), который определяет поведение и либо передают это в процедуру обработки, либо создает процедуру для регистрации интерфейсов для выполнения работы, а затем обработку подпрограмма просит регистратора для объекта обрабатывать часть работы для него.

Ответ 2

В деталях того, что вы планируете решить, возможно, вам стоит рассмотреть расширяемый парсер, например lua, вместо того, чтобы создавать свои собственные.

К вашему более конкретному фокусу.
DLL (обычно?) Должна быть полной сама по себе или явно знать, какие другие библиотеки использовать для завершения.

Я имею в виду, что вы не можете иметь метод, неявно предоставляемый вызывающим приложением для выполнения функций DLL.

Однако вы могли бы сделать часть вашего API предоставлением методов из вызывающего приложения, таким образом сделав DLL полностью содержащейся и передав знание явным.

Как использовать классы и функции в DLL?
Включите заголовки в свой код, когда модуль (exe или другая dll) связан, dll проверяются на завершение.

Может ли функция вызова DLL из программы связываться с ней?
Да, но о них нужно рассказывать во время выполнения.

Если я создаю объект класса <. >; в DLL, тогда, когда DLL загружается программой, объект будет доступен для программы?
Да, он будет доступен, однако есть некоторые ограничения, о которых вам нужно знать. Например, в области управления памятью важно либо:

  • Свяжите все модули, совместно использующие память, с одной и той же DLL-памятью управления (обычно c runtime)
  • Убедитесь, что память выделена и освобождена только в том же модуле.
  • выделить в стек

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

Что вам нужно - это способ регистрации функций (и их данных с помощью dll.) Большей проблемой здесь является бит детали. Но пропуская это, вы можете сделать что-то вроде wxWidgets с регистрацией классов. Когда method_fred будет обработан вашим приложением, он вызовет конструктор и зарегистрируется в DLL через использование off methodInfo. Parser может искать метод infoInfo для доступных методов.

Ответ 3

Это похоже на работу для структур данных.

Создайте структуру, содержащую ваши ключевые слова и функцию, связанную с каждой из них.

Затем напишите функцию в вашей DLL, в которой вы передаете адрес этого массива:

Затем внутри DLL он может делать:

С помощью этого метода код для обработки script ключевых слов остается в основной программе, тогда как DLL манипулирует структурами данных для вызова своих собственных функций.

Взяв его на С++, создайте вместо него класс class, который содержит карту std::vector или std:: или какие-либо ключевые слова и некоторые функции для их управления.

Ответ 4

Winrawr, прежде чем продолжить, прочитайте это сначала:

В основном вы можете столкнуться с проблемами при передаче строк STL вокруг ваших DLL, и у вас могут также возникнуть проблемы с исключениями, пролетающими через границы DLL, хотя это не то, что я испытал (пока).

Читайте также: