Как сделать модуль в с

от admin

Модули (с C++20)

В большинстве проектов C++ используется несколько единиц перевода, поэтому им необходимо совместно использовать объявления и определения в этих единицах. Для этой цели характерно использование файлов заголовков, примером которых является стандартная библиотека, объявления которой предоставляются с помощью #include -ing соответствующего заголовка.

Модули-это языковая функция для совместного использования деклараций и определений в единицах перевода.Они являются альтернативой некоторым случаям использования заголовочных файлов.

Syntax

export (optional) module module-namemodule-partition(optional)attr(optional) ; (1)
export declaration (2)
export

(3)
export (optional) import module-nameattr(optional) ; (4)
export (optional) import module-partitionattr(optional) ; (5)
export (optional) import header-nameattr(optional) ; (6)
module ; (7)
module : private ; (8)

Module declarations

Единицы перевода могут иметь объявление модуля,в этом случае они считаются module unit . The module declaration , если указано, должно быть первым объявлением единицы перевода (за исключением фрагмент глобального модуля , что будет рассмотрено позже). Каждый модуль модуля связан с module name (и, возможно, раздел), указанный в объявлении модуля.

export (optional) module module-namemodule-partition(optional)attr(optional) ;

Имя модуля состоит из одного или нескольких идентификаторов, разделенных точками (например: mymodule , mymodule.mysubmodule , mymodule2 . ). Точки не имеют внутреннего значения, однако они используются неофициально для обозначения иерархии.

A named module это совокупность модулей с одинаковым именем модуля.

Модули, в объявлении которых есть ключевое слово export , интерфейсные блоки модулей . Другие модульные единицы называются единицы реализации модуля .

Для каждого именованного модуля должен существовать ровно один интерфейсный блок модуля,в котором не указан раздел модуля.Этот модуль называется интерфейсный блок первичного модуля . Его экспортированное содержимое будет доступно при импорте соответствующего именованного модуля.

Экспорт деклараций и определений

Единицы интерфейса модуля могут экспортировать объявления и определения, которые могут быть импортированы другими единицами перевода. Перед ними может стоять ключевое слово export , либо они могут находиться внутри блока export .

export declaration
export

Импорт модулей и заголовков

Модули могут быть импортированы с помощью import declaration :

export (optional) import module-nameattr(optional) ;

Все объявления и определения,экспортированные в интерфейсные блоки модуля данного именованного модуля,будут доступны в блоке трансляции с помощью объявления import.

Декларации импорта могут быть экспортированы в единицу интерфейса модуля.То есть,если модуль A export-imports B,то импортирование A также сделает видимыми все экспорты из B.

В модулях все объявления импорта (включая экспорт-импорт)должны быть сгруппированы после объявления модуля и перед всеми другими объявлениями.

#include не следует использовать в модуле модуля (вне фрагмент глобального модуля ), потому что все включенные объявления и определения будут считаться частью модуля. Вместо этого заголовки также можно импортировать с import declaration :

export (optional) import header-nameattr(optional) ;

Импорт файла заголовка сделает доступными все его определения и объявления. Макросы препроцессора также доступны (поскольку объявления импорта распознаются препроцессором). Однако, в отличие от #include , макросы предварительной обработки, определенные в единице перевода, не повлияют на обработку файла заголовка. В некоторых случаях это может быть неудобно (некоторые заголовочные файлы используют макросы предварительной обработки в качестве формы конфигурации), и в этом случае использование фрагмент глобального модуля is needed.

Фрагмент глобального модуля

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

Если модуль-модуль имеет глобальный фрагмент модуля, то его первым объявлением должен быть module; . Тогда во фрагменте глобального модуля могут появиться только директивы препроцессинга . Затем стандартное объявление модуля отмечает конец фрагмента глобального модуля и начало содержимого модуля.

Фрагмент частного модуля

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

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

Module partitions

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

Раздел модуля представляет собой ровно одну единицу модуля (две единицы модуля не могут обозначать один и тот же раздел модуля).Они видны только из именованного модуля (блоки трансляции вне именованного модуля не могут импортировать раздел модуля напрямую).

Раздел модуля может быть импортирован модулями модуля с тем же именем.

export (optional) import module-partitionattr(optional) ;

Все определения и объявления в разделе модуля видны импортирующему модулю,независимо от того,экспортированы они или нет.

Разделы модуля могут быть модулями интерфейса модуля (когда в их объявлениях модуля есть export ). Они должны быть экспортированы-импортированы модулем интерфейса основного модуля, и их экспортированные операторы будут видны при импорте модуля.

Как создать свой модуль на С++

Помогите пожалуйста, как создовать собсвенные модули на С++, если не трудно, лучше на примере.

Мне кажется, вместо того, чтобы задавать такие вопросы пачками, лучше всего взять какую-либо хорошую книжку по C++ и начать по ней заниматься.

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

Про один из возможных подходов к изучению C++ с соответствующими книгами можете посмотреть здесь.

Пишем модуль на C++ для nodejs на примере работы с MySQL

Многие уже успели попробовать Node.js, на мой взгляд, это очень удобный инструмент, для решения большого круга задач. Меня в Node.js, прежде всего, привлекает возможность писать код на JavaScript и большой набор встроенных модулей для решения часто возникающих задач. Если чего-то не оказалось в стандартной поставке, то огромное количество дополнительных модулей можно найти в репозитории npmjs.org

Однако, бывают ситуации, когда всё, что там имеется, работает или не так, как хочется, или вообще не работает в заданных условиях, или же всё куда банальнее — просто отсутствует то, что необходимо для конкретного случая. Мне понадобился модуль, который может синхронно выполнять запросы к MySQL, причём четвёртой версии. Первый испытанный модуль работал исключительно с пятой версией, позже конечно нашлись другие, но найти тот, который позволяет выполнять запросы синхронно так и не удалось.

После изучения документации, я пришёл к выводу что, могу написать нужный мне модуль на C++ и оформить его как addon к node.js, если вам интересно познакомится с процессом создания модуля, добро пожаловать под кат.

Инструменты
  • mysql
  • node
  • node-gyp
  • GCC
Пишем модуль

Итак node.js — это платформа, построенная на JavaScript движке от Google V8. Соответственно, в нашем модуле нам придётся иметь дело с объектами движка V8. Чтобы упростить себе жизнь, желательно иметь какую-ни будь шпаргалку по объектам этого движка, я выбрал вот эту, а также справочник по функциям Си для работы с MySQL, например можно посмотреть здесь.

С чего начинаются модули

Для начала нужно создать файл, в моём случае это будет mysql_sync.cc, после опишем необходимые заголовки и зададим нэймспейс:

Работа любого модуля для node.js начинается с выполнения макроса NODE_MODULE, в который передаётся имя модуля и имя функции, которая будет выполнятся в момент подключения модуля.

Итак, мы видим что, функция init ничего не возвращает, но в неё передаётся объект. Мы добавляем свойство к этому объекту с именем create, при помощи метода Set, имя является объектом класса V8 String и создаётся при помощи статической функции NewSymbol, в которую мы передаём нужную строку. Значением этого свойства будет функция, которая будет создана из функции c именем create.
Всё достаточно просто, но есть одно но, данная функция будет вызвана только один раз при первой загрузке модуля, после чего node прокэширует у себя объект, который получен на выходе из функции init, и больше вызывать её не будет.
Если сейчас дописать функцию create, cкомпилировать модуль, и выполнить следующий код в node

В результате на экране увидим вот такой результат:

Первый этап готов, переходим к функции create.

Создание объекта нашего модуля

Код функции create ничем сложным не отличается:

Возвращаемым значением этого кода является объект класса V8 Value. Этот класс возвращают все функции JavaScript, а также С++, если они вызываются из JavaScript. Создаём новый объект ret, в котором будем хранить свойства возвращаемого функцией объекта. Тут нам, желательно, проинициализировать указатель на структуру MYSQL, которая понадобится для работы с остальными функциями MySQL и как-то её хранить в нашем объекте. Из всего, найденного более всего для хранения структуры подходил объект Buffer, который описан в самой node.js. С помощью конструкции node::Buffer::New мы создали новый объект нужного размера и положили туда проинициализированную структуру MYSQL (я знаю, что тут хорошо было бы проверить возвращаемый результат, но не хочется переусложнять, поэтому дальше будут опущены некоторые проверки).
Для того чтобы хранить MYSQL в нашему объекте но не давать пользователю к ней доступ был выбран вариант хранение структуры в скрытом поле объекта это делается при помощи метода SetHiddenValue, он полностью аналогичен методу Set за исключение того что создаёт не обычное свойство, а скрытое, то есть недоступное из JavaScript кода. Также в скрытом поле мы будем хранить свойство connected, оно нам пригодится позже, а сейчас положим в него объект V8 Boolean ( со значением False). После мы добавляем ещё две функции: connect и query. И в конце возвращаем наш объект, вызвавшей его функции, используя scope.Close(ret);
В промежуточном итоге мы полуаем функцию, которая создаёт новый объект, добавляя в него два срытых свойства со служебными данными для этого объекта, и два публичных свойства, в которых хранятся нужные нам функции.
Если сделать заглушки на две указанные функции и выполнить указанный код:

То получим следующий результат:

Методы нашего модуля

Теперь, опишем методы нашего модуля:
Метод connect:

Тут я столкнулся с первой трудностью, нам явно никак не передаётся объект который вызвал этот метод, а ведь в объекте хранится два скрытых поля которые нам необходимы для дальнейшей работы. Но аргументы в функцию передаются объектом V8 Arguments, покопавшись в его описании, находим, что он хранит ссылку на объект, который его передал. Чтобы её получить используем метод Holder(), после чего получаем скрытое поле со структурой MYSQL и при помощи метода GetIndexedPropertiesExternalArrayData() получаем указатель на на саму структуру. Дальше ничего примечательного в коде нет, идут проверки на то сколько было передано параметров и какого типа. Если всё правильно вызываем функцию mysql_real_connect(), получаем ошибки mysql, создаём объект err и складываем туда ошибки как значения полей. Если параметры не те что ожидали добавляем свою ошибку в объект err. Потом добавляем объект err как поле «err» к объекту ret и возвращаем этот объект.

Функция abs

Функция вычисляет абсолютную величину (модуль) значения, передаваемого в качестве аргумента через параметр n.
В C++, эта функция перегружена в заголовочном файле <cmath> для типов данных с плавающей точкой (см. функция abs в cmath ), в заголовочном файле <complex> — для комплексных чисел (см. функция abs для комплексных чисел), а в <valarray> для массивов целых чисел (см. функция abs в valarray ).

В языке программирования Си существует функция для вычисления модуля только целых чисел.

Читать:
Как пользоваться x mouse button control

Похожие статьи