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

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

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

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

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

Також треба завантажити файл РМв1.в (наприклад з GitHub-у).

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

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

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

extern "C" double mavka_extension_sum(double a, double b) { return a + b; }

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

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

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

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

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

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

Пробуємо:

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

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

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


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