Книга «WebAssembly в действии»

WebAssembly обеспечивает большую скорость, возможности повторного использования существующего кода и доступ к новым и более быстрым библиотекам. Кроме того, при необходимости вы можете настроить взаимодействие с JavaScript.

Книга была написана, чтобы помочь вам понять, что такое WebAssembly, как он работает и что с ним можно и нельзя сделать. Она показывает разные варианты сборки модуля WebAssembly в зависимости от ваших потребностей. Мы начинаем с простых примеров и затем переходим к более сложным темам, например к динамическому связыванию, параллельной обработке и отладке.

Создание модуля WebAssembly, вызывающего JavaScript

В главе 4 вы создали модуль WebAssembly, который вызывал JavaScript-код с помощью вспомогательной функции ccall из Emscripten. Буфер передавался в качестве параметра функции модуля, чтобы в случае возникновения проблемы можно было вернуть сообщение об ошибке, поместив его в буфер. Если возникает проблема, то JavaScript считывает строку из памяти модуля и затем отображает сообщение пользователю, как показано на рис. 5.1.

Представьте, что вместо передачи буфера функции модуля в случае возникновения проблемы модуль может просто передать сообщение об ошибке непосредственно в ваш JavaScript-код, как показано на рис. 5.2.

Используя набор инструментов Emscripten, вы можете взаимодействовать с кодом JavaScript из вашего модуля тремя способами.

  1. Использовать макросы Emscripten. К ним относятся серия макросов emscripten_run_script, макрос EM_JS и серия макросов EM_ASM.
  2. Добавить собственный JavaScript-код в файл JavaScript в Emscripten, который можно использовать напрямую.
  3. Задействовать указатели на функции, в которых код JavaScript указывает функцию, вызываемую модулем. Мы рассмотрим этот подход в главе 6.

При любом способе взаимодействия с JavaScript из модуля один подход может работать лучше, чем другой, в определенных обстоятельствах.

1. Макросы Emscripten могут быть весьма полезны при отладке или когда нужно только взаимодействие с кодом JavaScript напрямую. По мере увеличения сложности кода макроса или количества взаимодействий с JavaScript вы можете рассмотреть возможность отделения кода макроса от кода на C или C++.. Это следует сделать, чтобы упростить сопровождение кода и вашего модуля, и веб-страницы.

Когда используются серии макросов EM_JS и EM_ASM, на самом деле компилятор Emscripten создает необходимые функции и добавляет их в сгенерированный файл JavaScript в Emscripten. Вызывая макросы, модуль WebAssembly в действительности вызывает сгенерированные функции JavaScript.

СПРАВКА
Более подробную информацию о макросах Emscripten, в том числе о том, как их использовать, можно найти в приложении В.

2. Как вы увидите в данной главе, вызывать JavaScript напрямую несложно, и это несколько упростит JavaScript вашего сайта. Если вы планируете вызывать функции из функции JavaScript, размещенной в сгенерированном Emscripten JavaScript-коде, то вам необходимо иметь какое-то представление об основном коде JavaScript. Если вы поставляете модуль третьей стороне, то потребуются четкие инструкции по правильной настройке модуля, чтобы не было ошибок, — например, о том, что функция не существует.

ПРЕДУПРЕЖДЕНИЕ
Если вы планируете использовать этот подход вместе с Node.js, то JavaScript-код, который вы добавляете в сгенерированный файл JavaScript, должен быть автономным. Работа с Node.js рассматривается более подробно в главе 10, но, по сути, из-за того, как Node.js загружает файл JavaScript в Emscripten, код в этом файле не может вызывать ваш основной JavaScript-код.

3. В главе 6 вы увидите, что использование указателей на функции дает гораздо больше гибкости, поскольку модулю не нужно знать, какие функции существуют в вашем JavaScript-коде. Вместо этого модуль просто вызовет предоставленную JavaScript-функцию. Дополнительная гибкость указателей на функции связана с немного большей сложностью, поскольку такой подход требует большего количества кода на JavaScript, чтобы все работало правильно.

Вместо того чтобы позволять Emscripten создавать функции JavaScript с помощью макросов, вы можете определить собственный JavaScript, который будет включен в файл JavaScript в Emscripten. Мы изучим такой подход в данной главе.

В рамках этого сценария мы изменим модуль валидации, созданный в главе 4, чтобы при возникновении проблемы при валидации сообщение об ошибке не передавалось обратно вызывающей функции с помощью параметра.. Вместо этого вы сделаете следующее (рис. 5.3).

  1. Если была найдена проблема с пользовательским вводом, то пусть модуль вызовет функцию JavaScript, которую вы поместите в созданный Emscripten файл JavaScript.
  2. Функция JavaScript будет принимать указатель от модуля и считывать сообщение об ошибке из памяти модуля.
  3. Затем она передаст сообщение в основной JavaScript веб-страницы, где будет обработано обновление пользовательского интерфейса с полученной ошибкой.

Использование C или C++ для создания модуля со связующим кодом EMSCRIPTEN

Вернемся к логике валидации в C++, созданной в главе 4, и изменим ее так, чтобы она могла взаимодействовать с кодом на JavaScript. Добавим стандартную библиотеку C и вспомогательные функции Emscripten — это рекомендуемый способ создания модуля, предназначенного для использования в производственной среде. Позже в данной главе мы рассмотрим и другой подход к созданию модуля WebAssembly, который не включает стандартную библиотеку C или вспомогательные функции Emscripten.

Как показано на рис. 5.4, шаги по созданию модуля будут аналогичны шагам в главе 4.

  1. Измените код на C++ так, чтобы он больше не получал строковый буфер и вместо этого вызывал функцию JavaScript в случае проблемы с валидацией.
  2. Определите JavaScript-код, который нужно добавить в созданный Emscripten файл JavaScript.
  3. Дайте Emscripten команду сгенерировать связующие файлы WebAssembly и JavaScript.
  4. Скопируйте созданные файлы для использования в браузере.
  5. Создайте веб-страницу, а затем напишите JavaScript-код, необходимый для взаимодействия с модулем WebAssembly.

Внесение изменений в код на C++

На рис. 5.5 видно, что первый шаг процесса — изменение кода на C++, чтобы он больше не получал строковый буфер. Вместо этого код вызовет функцию JavaScript, передав ей сообщение об ошибке при обнаружении проблемы с валидацией.

В папке WebAssembly создайте папку Chapter 55.1.1 EmJsLibrarysource для файлов, которые будут использоваться в этом подразделе. Скопируйте файл validate.cpp из папки WebAssemblyChapter 44.1 js_plumbingsource в новую папку source. Откройте файл validate.cpp в своем любимом редакторе.

Сейчас вы измените код C++ так, чтобы вызвать функцию, определенную в JavaScript. Поскольку функция не является частью кода на C++, нужно сообщить компилятору о сигнатуре функции, добавив ключевое слово extern перед сигнатурой. Это позволяет компилировать код C++, ожидая, что функция будет доступна при запуске кода. Когда компилятор Emscripten видит сигнатуру функции, он создает для нее запись импорта в модуле WebAssembly. При создании экземпляра модуля фреймворк WebAssembly увидит запрошенный импорт и будет ожидать, что в JavaScript-файле будет предоставлена соответствующая функция.

Будущая функция в JavaScript принимает указатель const char* для параметра, который будет хранить сообщение об ошибке, если возникнет проблема с проверкой. Функция не возвращает значение. Чтобы определить сигнатуру функции, добавьте следующую строку кода в блок extern «C» и перед функцией ValidateValueProvided в файле validate.cpp:

Поскольку вы больше не собираетесь передавать буфер в модуль, необходимо удалить параметры char* return_error_message из функций. Кроме того, любой код, вызывающий strcpy для копирования сообщения об ошибке в буфер, теперь должен будет вместо этого вызвать функцию UpdateHostAboutError.

Измените функцию ValidateValueProvided, убрав параметр return_error_message, и добавьте вызов функции UpdateHostAboutError, а не strcpy, как показано ниже:

Подобно функции ValidateValueProvided, измените функцию ValidateName, чтобы она больше не получала параметр return_error_message, и удалите его из вызова функции ValidateValueProvided. Измените код, чтобы теперь сообщение об ошибке передавалось в функцию UpdateHostAboutError вместо использования strcpy, как показано ниже:

В функции IsCategoryIdInArray никаких изменений не требуется.

Наконец, необходимо внести те же изменения, что и для функций ValidateValueProvided и ValidateName, в функцию ValidateCategory, как показано в листинге 5.1.

С полным содержанием статьи можно ознакомиться на сайте “Хабрахабр”:

https://habr.com/ru/company/piter/blog/586692/

Источник



Leave A Reply

Your email address will not be published.