diff --git a/files/ru/webassembly/c_to_wasm/index.md b/files/ru/webassembly/c_to_wasm/index.md index 83503987b337e3..61f0b28d2fb8af 100644 --- a/files/ru/webassembly/c_to_wasm/index.md +++ b/files/ru/webassembly/c_to_wasm/index.md @@ -3,183 +3,160 @@ title: Компиляция кода C/C++ в WebAssembly slug: WebAssembly/C_to_wasm translation_of: WebAssembly/C_to_wasm --- -
После того как вы написали код на C / C ++, вы можете скомпилировать его в WebAssembly, например, с помощью инструмента Emscripten. Давайте посмотрим, как это работает.
+После того как вы написали код на C / C ++, вы можете скомпилировать его в WebAssembly, например, с помощью инструмента [Emscripten](/ru/docs/Mozilla/Projects/Emscripten). Давайте посмотрим, как это работает. -Первым делом установим компоненты для дальнейшей работы.
+Первым делом установим компоненты для дальнейшей работы. -Установите Emscripten SDK и настройте рабочее окружение используя инструкции: https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
+Установите Emscripten SDK и настройте рабочее окружение используя инструкции:Когда рабочее окружение подготовлено, попробуем собрать пример кода на языке Си при помощи Emscripten. Вам доступно большое количество опций для настройки компиляции, но мы рассмотрим только два основных сценария компиляции с использованием Emscripten:
+Когда рабочее окружение подготовлено, попробуем собрать пример кода на языке Си при помощи Emscripten. Вам доступно большое количество опций для настройки компиляции, но мы рассмотрим только два основных сценария компиляции с использованием Emscripten: -Мы рассмотрим оба способа ниже.
+Мы рассмотрим оба способа ниже. -Это самый простой способ, который мы рассмотрим. С его помощью вы сможете использовать Emscripten для создания всего что нужно, чтобы ваш код работал в браузере как модуль WebAssembly.
+Это самый простой способ, который мы рассмотрим. С его помощью вы сможете использовать Emscripten для создания всего что нужно, чтобы ваш код работал в браузере как модуль WebAssembly. -hello.c
в новой папке на вашем локальном диске:
+1. Нам понадобится простой пример для компиляции. Скопируйте следующий код программы на Си и сохраните его в файле `hello.c` в новой папке на вашем локальном диске:
- #include <stdio.h> + ```cpp + #include--int main(int argc, char ** argv) { - printf("Hello World\n"); -}
emcc hello.c -s WASM=1 -o hello.html-
Рассмотрим параметры, которые мы передали компилятору:
+2. Теперь, используя терминал, перейдите в каталог, в котором находится ваш файл hello.c, и выполните следующую команду: --s WASM=1
— Указывает, что мы хотим получить wasm модуль. Если не использовать этот параметр, по умолчанию Emscripten просто создаёт asm.js;-o hello.html
— Указывает, что мы хотим, чтобы Emscripten сгенерировал HTML-страницу hello.html
запускающую наш код, а также сам модуль wasm и код JavaScript который позволит использовать модуль в веб-среде.На этом этапе в вашем каталоге должны находится:
+Рассмотрим параметры, которые мы передали компилятору: -hello.wasm
)hello.js
)hello.html
)Теперь, всё что нужно чтобы запустить полученный hello.html
в браузере, это поддержка WebAssembly. Он включён по умолчанию в Firefox 52+, Chrome 57+ и последних версиях Opera. Также вы можете использовать модули WebAssembly в Firefox 47+, включив флаг javascript.options.wasm
в about:config, или в Chrome 51+ и Opera 38+ перейдя в chrome://flags и включив флаг Experimental WebAssembly.
Если все работает как планировалось, вы должны увидеть надпись "Hello world" на открывшейся веб-странице и в JavaScript консоли вашего браузера. Поздравляем, вы только что скомпилировали программу на Си в WebAssembly и запустили её в своём браузере!
+### Запуск вашего примера -Примечание: На самом деле, если просто открыть полученный hello.html
, то ничего работать не будет. Подразумевается что все файлы находятся на веб-сервере и вы запускаете страницу через localhost/hello.html
. Для этих целей можно использовать отладочный веб-сервер Emscripten. Чтобы его запустить, откройте терминал, перейдите в каталог, в котором находятся ваши файлы и выполните команду emrun hello.html
Вы можете использовать собственный шаблон HTML. Давайте посмотрим, как это сделать:
+> **Примечание:** На самом деле, если просто открыть полученный `hello.html`, то ничего работать не будет. Подразумевается что все файлы находятся на веб-сервере и вы запускаете страницу через `localhost/hello.html`. Для этих целей можно использовать отладочный веб-сервер Emscripten. Чтобы его запустить, откройте терминал, перейдите в каталог, в котором находятся ваши файлы и выполните команду `emrun hello.html` -Прежде всего, сохраните следующий код в файле hello2.c в новом каталоге:
+### Использование собственного HTML шаблона -#include <stdio.h> +Вы можете использовать собственный шаблон HTML. Давайте посмотрим, как это сделать: -int main(int argc, char ** argv) { - printf("Hello World\n"); +1. Прежде всего, сохраните следующий код в файле hello2.c в новом каталоге: -}-
Найдите файл shell_minimal.html
в вашем репозитории emsdk. Скопируйте его в подкаталог html_template
внутри вашего нового каталога.
Теперь, используя терминал, перейдите в ваш новый каталог и выполните следующую команду:
+ ```cpp + #includeemcc -o hello2.html hello2.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html+ int main(int argc, char ** argv) { + printf("Hello World\n"); -
В этот раз мы использовали немного другие параметры компиляции:
+ } + ``` --o hello2.html
, чтобы компилятор по прежнему генерировал необходимый JavaScript-код и .html
файл.--shell-file html_template/shell_minimal.html
чтобы компилятор использовал ваш шаблон для создания HTML страницы запускающей этот пример.Теперь давайте запустим этот пример. Команда, указанная выше, сгенерирует файл hello2.html
, который будет иметь тоже содержание что и шаблон, но с некоторым кодом, добавленным в процесс загрузки сгенерированного wasm, запускающим его и т.д. Откройте его в своём браузере, и вы увидите тот же результат, что и прошлом примере.
Примечание: вы можете указать компилятору создавать только JavaScript-кода, без HTML, используя внутри флага -o
, .js
вместо .html
для формата выходного файла, например emcc -o hello2.js hello2.c -O3 -s WASM=1
. После этого вы должны создать свой собственный HTML файл с нуля. Однако так делать не рекомендуется — Emscripten требуется большое количество связывающего кода для обработки операций выделения памяти, утечек памяти и других проблем, которые уже включены в предоставляемый шаблон. Намного легче использовать уже готовое решение, чем создавать свои собственные версии самому.
Если у вас есть функция определённая в коде на Си, которую вы хотите по необходимости вызывать из JavaScript, то вы можете использовать для этого функцию ccall()
из Emscripten, и объявление EMSCRIPTEN_KEEPALIVE
которое добавит вашу функцию в список экспортируемых функций (см. Почему функции в моем коде исчезают после компиляции и/или я получаю сообщение «Нет функций для обработки»). Давайте посмотрим, как это работает.
Для начала сохраните следующий код в файле hello3.c
в новом каталоге:
#include <stdio.h> -#include <emscripten/emscripten.h> +> **Примечание:** вы можете указать компилятору создавать только JavaScript-кода, без HTML, используя внутри флага `-o`, `.js` вместо `.html` для формата выходного файла, например `emcc -o hello2.js hello2.c -O3 -s WASM=1`. После этого вы должны создать свой собственный HTML файл с нуля. Однако так делать не рекомендуется — Emscripten требуется большое количество связывающего кода для обработки операций выделения памяти, утечек памяти и других проблем, которые уже включены в предоставляемый шаблон. Намного легче использовать уже готовое решение, чем создавать свои собственные версии самому. -int main(int argc, char ** argv) { - printf("Hello World\n"); -} +### Вызов пользовательской функции, определённой в Си -#ifdef __cplusplus -extern "C" { -#endif - -void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) { - printf("MyFunction Called\n"); -} - -#ifdef __cplusplus -} -#endif- -
По умолчанию, код созданный Emscripten, всегда просто вызывает функцию main()
, а остальные неиспользуемые функции удаляются. Добавьте определение EMSCRIPTEN_KEEPALIVE
перед именем функции чтобы этого не происходило. Также вы должны подключить библиотеку emscripten.h
для использования EMSCRIPTEN_KEEPALIVE
.
Примечание: Мы используем блоки #ifdef
чтобы, пример оставался рабочим если вы попытаетесь использовать C++ код. Из за различия в правилах преобразования имён между Си и Си++, этот код может сломаться, но мы написали его так, что функция будет рассматриваться как функция Си даже если вы будете использовать Си++.
Теперь добавьте html_template/shell_minimal.html
в ваш новый каталог, просто для удобства. В настоящем проекте стоит размещать его в специально определённый каталог.
Теперь снова займёмся этапом компиляции. Внутри вашего последнего каталога, используя терминал, скомпилируйте ваш Си код следующей командой. (Обратите внимание что при компиляции обязательно нужно использовать опцию NO_EXIT_RUNTIME, иначе после выполнения функции main()
, рабочий цикл будет завершён. Это приведёт, например, к вызову функции atexits и дальше будет невозможно использовать наш скомпилированный код. Другими словами это необходимо для правильной эмуляции Си.)
emcc -o hello3.html hello3.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall"]'-
Если вы снова запустите пример в своём браузере, вы увидите тоже самое что и до этого!
-Теперь нам нужно вызвать нашу новую функцию myFunction()
из JavaScript. Прежде всего, добавьте {{htmlelement("button")}} как показано ниже, чуть выше первого открывающего тега <script type='text/javascript'>
.
<button class="mybutton">Run myFunction</button>-
Теперь добавьте следующий код в конце первого элемента {{htmlelement("script")}} (чуть выше закрывающего тега </script>
):
document.querySelector('.mybutton').addEventListener('click', function(){ - alert('check console'); - var result = Module.ccall('myFunction', // name of C function - null, // return type - null, // argument types - null); // arguments -});-
Это показывает как использовать ccall()
для вызова экспортируемой функции.
В этой статье объясняются концепции, лежащие в основе работы технологии WebAssembly, включая её цели, проблемы, которые она решает, и то, как она работает в движке рендеринга веб-браузера.
+В этой статье объясняются концепции, лежащие в основе работы технологии WebAssembly, включая её цели, проблемы, которые она решает, и то, как она работает в движке рендеринга веб-браузера. -WebAssembly - это технология, предоставляющая новый тип кода, который можно запускать в современных веб-браузерах, что обеспечивает новые функции и значительное повышение производительности. Код для WebAssembly не предназначен для написания вручную, скорее он спроектирован для эффективной компиляции из низкоуровневых исходных языков, таких как C, C++, Rust и.т.д.
+WebAssembly - это технология, предоставляющая новый тип кода, который можно запускать в современных веб-браузерах, что обеспечивает новые функции и значительное повышение производительности. Код для WebAssembly не предназначен для написания вручную, скорее он спроектирован для эффективной компиляции из низкоуровневых исходных языков, таких как C, C++, Rust и.т.д. -WebAssembly позволяет запускать код, написанный на различных языках в web-приложениях почти c естественной скоростью. Это имеет огромное значение для веб-платформы, так как ранее это нельзя было сделать.
+WebAssembly позволяет запускать код, написанный на различных языках в web-приложениях почти c естественной скоростью. Это имеет огромное значение для веб-платформы, так как ранее это нельзя было сделать. -Более того, вам даже не нужно знать, как создавать код WebAssembly, чтобы его использовать. Модули WebAssembly можно импортировать в веб-приложение (или Node.js), и экспортировать из них функции для использования через JavaScript. JavaScript-фреймворки могут использовать модули WebAssembly для получения огромных преимуществ в производительности и новых функций, в то же время делая их функциональность легко доступной для веб-разработчиков.
+Более того, вам даже не нужно знать, как создавать код WebAssembly, чтобы его использовать. Модули WebAssembly можно импортировать в веб-приложение (или Node.js), и экспортировать из них функции для использования через JavaScript. JavaScript-фреймворки могут использовать модули WebAssembly для получения огромных преимуществ в производительности и новых функций, в то же время делая их функциональность легко доступной для веб-разработчиков. -Технология WebAssembly создаётся как открытый стандарт внутри W3C WebAssembly Community Group со следующими целями:
+Технология WebAssembly создаётся как открытый стандарт внутри [W3C WebAssembly Community Group](https://www.w3.org/community/webassembly/) со следующими целями: -Примечание: Технология WebAssembly также будет иметь возможность использования за пределами веб и JavaScript-сред (см. Встраивание вне Web).
-Веб-платформа может рассматриваться как состоящая из двух частей:
+Веб-платформа может рассматриваться как состоящая из двух частей: -Исторически ВМ могла загружать только JavaScript. Раньше нас это вполне устраивало, поскольку JavaScript достаточно мощный, чтобы решать большинство проблем, с которыми мы сталкивались в интернете. Однако мы столкнулись с проблемами производительности, когда попытались использовать JavaScript для более нагруженных сценариев использования, таких как 3D-игры, виртуальная и дополненная реальность, компьютерное зрение, редактирование изображений / видео и в ряде других применений, которые требуют повышенной производительности (см. варианты использования WebAssembly где описано больше идей).
+Исторически ВМ могла загружать только JavaScript. Раньше нас это вполне устраивало, поскольку JavaScript достаточно мощный, чтобы решать большинство проблем, с которыми мы сталкивались в интернете. Однако мы столкнулись с проблемами производительности, когда попытались использовать JavaScript для более нагруженных сценариев использования, таких как 3D-игры, виртуальная и дополненная реальность, компьютерное зрение, редактирование изображений / видео и в ряде других применений, которые требуют повышенной производительности (см. [варианты использования WebAssembly](http://webassembly.org/docs/use-cases/) где описано больше идей). -Кроме того, длительность загрузки, анализа и компиляции очень больших приложений JavaScript может быть непомерно высокой. Мобильные и другие ограниченные в ресурсах платформы могут ещё более понизить производительность.
+Кроме того, длительность загрузки, анализа и компиляции очень больших приложений JavaScript может быть непомерно высокой. Мобильные и другие ограниченные в ресурсах платформы могут ещё более понизить производительность. -Язык WebAssembly отличается от языка JavaScript, но он не предназначен для его замены. Он предназначен для дополнения и работы вместе с JavaScript, что позволяет веб-разработчикам использовать преимущества обоих языков:
+Язык WebAssembly отличается от языка JavaScript, но он не предназначен для его замены. Он предназначен для дополнения и работы вместе с JavaScript, что позволяет веб-разработчикам использовать преимущества обоих языков: -С появлением WebAssembly в браузерах виртуальная машина, о которой мы говорили ранее, теперь будет загружать и запускать два типа кода - JavaScript и WebAssembly.
+С появлением WebAssembly в браузерах виртуальная машина, о которой мы говорили ранее, теперь будет загружать и запускать два типа кода - JavaScript и WebAssembly. -Различные типы кода могут вызывать друг друга по мере необходимости - WebAssembly JavaScript API оборачивает экспортированный код WebAssembly в функции JavaScript, которые можно вызывать обычным способом. А в код WebAssembly можно импортировать и синхронно вызывать обычные функции JavaScript. Фактически, базовая единица кода WebAssembly называется модулем, а модули WebAssembly во многом схожи с модулями ES2015.
+Различные типы кода могут вызывать друг друга по мере необходимости - [WebAssembly JavaScript API](/ru/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) оборачивает экспортированный код WebAssembly в функции JavaScript, которые можно вызывать обычным способом. А в код WebAssembly можно импортировать и синхронно вызывать обычные функции JavaScript. Фактически, базовая единица кода WebAssembly называется модулем, а модули WebAssembly во многом схожи с модулями ES2015. -Есть несколько ключевых понятий, необходимых для понимания того, как WebAssembly работает в браузере. Все эти понятия отражены 1:1 в WebAssembly JavaScript API.
+Есть несколько ключевых понятий, необходимых для понимания того, как WebAssembly работает в браузере. Все эти понятия отражены 1:1 в [WebAssembly JavaScript API](/ru/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly). -postMessage()
). В модуле есть объявление импорта и экспорта точно такое же, как и в модуле ES2015.JavaScript API предоставляет разработчикам возможность создавать модули, объекты памяти, таблицы и экземпляры модулей. Получив экземпляр модуля WebAssembly, код JavaScript может синхронно вызывать его экспорты, которые представляются как обычные функции JavaScript. Любые функции JavaScript также могут синхронно вызываться кодом WebAssembly путём передачи этих функций в качестве импорта в экземпляр модуля WebAssembly.
+JavaScript API предоставляет разработчикам возможность создавать модули, объекты памяти, таблицы и экземпляры модулей. Получив экземпляр модуля WebAssembly, код JavaScript может синхронно вызывать его экспорты, которые представляются как обычные функции JavaScript. Любые функции JavaScript также могут синхронно вызываться кодом WebAssembly путём передачи этих функций в качестве импорта в экземпляр модуля WebAssembly. -Поскольку JavaScript полностью контролирует загрузку, компиляцию и запуск кода WebAssembly, разработчики JavaScript могут рассматривать технологию WebAssembly как расширение JavaScript для эффективной генерации высокопроизводительных функций.
+Поскольку JavaScript полностью контролирует загрузку, компиляцию и запуск кода WebAssembly, разработчики JavaScript могут рассматривать технологию WebAssembly как расширение JavaScript для эффективной генерации высокопроизводительных функций. -В будущем модули WebAssembly будут загружаться так же, как и модули ES2015 (с использованием <script type='module'>
), что означает, что JavaScript сможет извлекать, компилировать и импортировать модуль WebAssembly так же легко, как модуль ES2015.