Мавку, ще з часів 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.