Приложение Dart FFI и CLI
Как использовать Dart FFI и создать приложение с интерфейсом командной строки? Хм…
Все в одном ресурсе Flutter: https://flatteredwithflutter.com/dart-ffi-cli-dart2native/
Обсуждение на встрече:
Начинать…
Уровень: средний
Мы кратко расскажем о
- Использование Dart FFI
- Получение истории входа пользователя (macOS)
- Создать приложение CLI
Примечание. Мы не будем подробно рассказывать о Dart FFI, так как ему посвящены хорошие статьи.
- Использование Dart FFI
FFI: (Интерфейс внешних функций) можно использовать для вызова API на основе языка C / C ++.
Статически связанная библиотека встроена в исполняемый образ приложения и загружается при запуске приложения.
Символы из статически связанной библиотеки можно загрузить с помощью DynamicLibrary.executable
или DynamicLibrary.process
.
Динамически подключаемая библиотека распространяется в отдельном файле или папке в приложении и загружается по запросу. Динамически подключаемую библиотеку можно загрузить в Dart через DynamicLibrary.open
.
Как мы подойдем?
В этой статье мы будем использовать динамическую системную библиотеку.
Если вы хотите создать свою собственную динамическую библиотеку, прочтите это.
2. Получить историю входа пользователя (macOS).
Откройте терминал и введите эту команду
last login `username` where username is before @ [username@Macbook-Pro]
- Вы должны получить историю входа в систему. Наша цель - вызвать эту команду из Дарта.
- Эта команда определена в системной динамической библиотеке, присутствующей в macOS.
В macOS системные библиотеки присутствуют в
/usr/lib/libSystem.dylib
Чтобы получить пути для разных ОС, посетите здесь.
Мы загрузим нашу динамическую библиотеку, указанную по пути выше, в Dart.
- Импортируйте пакет dart ffi (присутствует внутри Flutter) как
import 'dart:ffi' as ffi
У этого есть класс DynamicLibrary. Мы вызываем метод open и загружаем нашу динамическую библиотеку (Dylibs.systemDyLib).
class Dylibs { static const String systemDyLib = '/usr/lib/libSystem.dylib'; static const String systemSymbolName = 'system'; }
Каждая динамическая библиотека состоит из символов. Чтобы найти символы в библиотеке, обратитесь сюда.
Теперь получение истории входа пользователя попадает под символ Система.
- Найдите символ в загруженной динамической библиотеке с помощью lookupFunction.
Мы указали функции SystemC и SystemDart, которые в основном
// C header typedef: typedef SystemC = ffi.Void Function(ffi.Pointer<Utf8> command); // Dart header typedef typedef SystemDart = void Function(ffi.Pointer<Utf8> command);
Это объединяет функцию поиска и приводит к функции Dart.
- Затем мы конвертируем команду (нашу последнюю команду входа в систему) во что-то, что C понимает, используя
/// Convert a [String] to a Utf8-encoded null-terminated C string. /// Returns a malloc-allocated pointer to the result. final cmd = Utf8.toUtf8(command);
- Запустите команду, используя
sysFunc(cmd)
- Наконец, освободите память, поскольку C / C ++ не поддерживает сборку мусора.
3. Создайте приложение с интерфейсом командной строки
Мы создадим нашу собственную команду, которая будет содержать информацию и описание приложения CLI.
- Создайте нашу команду
Мы используем CommandRunner и определяем нашу команду (last_login) с некоторым описанием как
- Добавьте нашу последнюю команду входа в систему. Чтобы создавать свои собственные команды, вам необходимо расширить Command Class
// THIS ADDS OUR LAST LOGIN COMMAND runner.addCommand(LastLoginCmd());
Примечание. LastLoginCmd - это наш собственный класс.
МЫ создаем класс абстрактной базовой команды и объявляем методы.
abstract class BaseCLICommand extends Command<dynamic> { String loadingMessage; void execCommand(String arg); @override Future<void> run() async { if (argResults.arguments.isEmpty) { throw Exception('😳😳 Please specify the argument'); } final arg = argResults.arguments.first; final loadingMsg = '$loadingMessage $arg'; stdout.write('$loadingMsg\n'); execCommand(arg); } }
- argResults.arguments помогают нам получать данные, введенные пользователем.
- stdout.write используется для вывода на консоль.
- execCommand - это функция, которую определяет расширенный класс.
Наш LastLoginCmd расширяет указанный выше класс и реализует методы.
- После того, как мы добавим команду, как указано выше
// THIS ADDS OUR LAST LOGIN COMMAND runner.addCommand(LastLoginCmd());
Наконец, мы запускаем эту команду как
runner.run(args);
Последний шаг (преобразование в приложение CLI)
Мы используем силу
dart2native
, который может компилировать программы Dart в автономные исполняемые файлы. С dart2native вы можете создавать инструменты для командной строки в macOS, Windows или Linux с помощью Dart.
- Перейдите в каталог, содержащий точку входа в дротик. Например
Мой каталог будет lib / ffi
2. Запустите команду
dart2native cmd_line.dart -o login_history
-o <path>
или --output=<path>
Создает вывод.
Это создает наше приложение CLI с именем login_history.
Окончательный результат
Интересные статьи, связанные с Flutter, здесь: