Вступ
ЧасописМавки

Як створити просте розширення Мавки?

Мавку, ще з часів JavaScript версії, можна розширювати. Раніше, очевидно, за допомогою JavaScript. На щастя, Мавка вже відійша від JS, тому сьогодні розширюватимемо за допомогою Цілі.

У цьому дописі я покажу як просто можна виконувати код на Цілі з Мавки. Але навіть більше — код на Сі через Ціль з Мавки.

Отож, поїхали. Для цього нам будуть треба останні версії Мавки, Цілі та Clang. На момент написання цього допису в мене версія Мавки 0.121.3, версія Цілі 0.40.0 та Clang.

Також треба файл РМв1.в.ц.

Структура директорії проекту буде така:

розширення_мавки_сума/ ├─ РМв1.в.ц ├─ sum_mavka_extension.c ├─ розширення_мавки_сума.ц.ll ├─ розширення_мавки_сума.so ├─ розширення_мавки_сума.ц └─ тест_розширення_сума.м

Створюємо файл sum_mavka_extension.c з наступним вмістом:

#define р64 double extern р64 додати_в_сі(р64 а, р64 б) { return а + б; }

Створюємо файл розширення_мавки_сума.ц з наступним вмістом:

взяти визначення РМв1; зовнішня дія додати_в_сі(а: р64, б: р64): р64; дія рідна_дія_сума(Р: адреса<РМв1::Розширення>, предмет_дії: адреса<РМв1::Предмет>, предмет_я: адреса<РМв1::Предмет>, кількість_аргументів: натуральне, аргументи: памʼять<адреса<РМв1::Предмет>>, іменовані_аргументи: адреса<РМв1::ІменованіАргументи>): РМв1::ПредметАбоСтанПадіння { змінна знайдено_аргумент_а = ні; змінна аргумент_а: адреса<РМв1::Предмет> = пусто; змінна знайдено_аргумент_б = ні; змінна аргумент_б: адреса<РМв1::Предмет> = пусто; якщо іменовані_аргументи != пусто { знайдено_аргумент_а = РМв1::знайти_іменований_аргумент(Р, іменовані_аргументи, РМв1::назва(Р, "а"), аргумент_а::адреса); знайдено_аргумент_б = РМв1::знайти_іменований_аргумент(Р, іменовані_аргументи, РМв1::назва(Р, "б"), аргумент_б::адреса); } якщо знайдено_аргумент_а == ні { якщо кількість_аргументів > 0 { знайдено_аргумент_а = так; аргумент_а = аргументи[0]; } } якщо знайдено_аргумент_б == ні { якщо кількість_аргументів > 1 { знайдено_аргумент_б = так; аргумент_б = аргументи[1]; } } якщо знайдено_аргумент_а == ні { вернути РМв1::падіння(Р, РМв1::створити_текст(Р, "Пропущено аргумент \"а\"")); } якщо знайдено_аргумент_б == ні { вернути РМв1::падіння(Р, РМв1::створити_текст(Р, "Пропущено аргумент \"б\"")); } якщо РМв1::перевірити_чи_предмет_є_числом(Р, аргумент_а) == ні { вернути РМв1::падіння(Р, РМв1::створити_текст(Р, "Аргумент \"а\" має бути числом")); } якщо РМв1::перевірити_чи_предмет_є_числом(Р, аргумент_б) == ні { вернути РМв1::падіння(Р, РМв1::створити_текст(Р, "Аргумент \"б\" має бути числом")); } змінна а = РМв1::отримати_значення_числа(Р, аргумент_а); змінна б = РМв1::отримати_значення_числа(Р, аргумент_б); змінна результат = додати_в_сі(а, б); вернути РМв1::створити_число(Р, результат); } зовнішня дія завантажити_РМв1(Р: адреса<РМв1::Розширення>): РМв1::ПредметАбоСтанПадіння { вернути РМв1::створити_рідну_дію( Р, РМв1::назва(Р, "сума"), 0, пусто, пусто, рідна_дія_сума ); }

Компілюємо shared object розширення_мавки_сума.so за допомогою наступних команд:

ціль розширення_мавки_сума.ц.ll скомпілювати розширення_мавки_сума.ц
clang -shared -fPIC -o розширення_мавки_сума.so розширення_мавки_сума.ц.ll sum_mavka_extension.c

Створюємо модуль Мавки тест_розширення_сума.м:

взяти біб мавка розширення_мавки_сума = мавка.завантажити_РМв1"./розширення_мавки_сума.so") друк(розширення_мавки_сума.значення(2, 2))

Пробуємо:

мавка тест_розширення_сума.м

Має надрукувати 4.

Отож, як видно, виконувати нативний код на Цілі чи Сі з Мавки досить просто. Головне розібратись з файлом РМв1.в.ц та вміти працювати з Ціллю.


Написав Давид. Опубліковано 01.12.2024. Оновлено 17.07.2025.