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

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

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

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

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

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

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

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

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

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

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

взяти визначення РМв1; зовнішня дія додати_в_сі(а: д64, б: д64): д64; дія рідна_дія_сума(Р: адреса<РМв1::Розширення>, предмет_дії: адреса<РМв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 за допомогою наступних команд:

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

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

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

Пробуємо:

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

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

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


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