aboutsummaryrefslogtreecommitdiff
path: root/files/ru/webassembly/c_to_wasm/index.html
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/webassembly/c_to_wasm/index.html
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/ru/webassembly/c_to_wasm/index.html')
-rw-r--r--files/ru/webassembly/c_to_wasm/index.html185
1 files changed, 185 insertions, 0 deletions
diff --git a/files/ru/webassembly/c_to_wasm/index.html b/files/ru/webassembly/c_to_wasm/index.html
new file mode 100644
index 0000000000..81e1dc93a3
--- /dev/null
+++ b/files/ru/webassembly/c_to_wasm/index.html
@@ -0,0 +1,185 @@
+---
+title: Компиляция кода C/C++ в WebAssembly
+slug: WebAssembly/C_to_wasm
+translation_of: WebAssembly/C_to_wasm
+---
+<div>{{WebAssemblySidebar}}</div>
+
+<p class="summary">После того как вы написали код на C / C ++, вы можете скомпилировать его в WebAssembly, например, с помощью инструмента <a href="/en-US/docs/Mozilla/Projects/Emscripten">Emscripten</a>. Давайте посмотрим, как это работает.</p>
+
+<h2 id="Подготовка_рабочей_среды_для_Emscripten">Подготовка рабочей среды для Emscripten</h2>
+
+<p>Первым делом установим компоненты для дальнейшей работы.</p>
+
+<h3 id="Необходимые_компоненты">Необходимые компоненты</h3>
+
+<p>Установите Emscripten SDK и настройте рабочее окружение используя инструкции: <a href="https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html">https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html </a></p>
+
+<h2 id="Компиляция_примера">Компиляция примера</h2>
+
+<p>Когда рабочее окружение подготовлено, попробуем собрать пример кода на языке Си при помощи Emscripten. Вам доступно большое количество опций для настройки компиляции, но мы рассмотрим только два основных сценария компиляции с использованием Emscripten:</p>
+
+<ul>
+ <li>Компиляция в wasm и созданиее HTML-страницы для запуска вашего кода, а также JavaScript кода, необходимого для работы wasm модуля в веб-среде.</li>
+ <li>Просто компиляция в wasm и создание JavaScript кода.</li>
+</ul>
+
+<p>Мы рассмотрим оба способа ниже.</p>
+
+<h3 id="Создание_HTML_и_JavaScript">Создание HTML и JavaScript</h3>
+
+<p>Это самый простой способ, который мы рассмотрим. С его помощью вы сможете использовать Emscripten для создания всего что нужно, чтобы ваш код работал в браузере как модуль WebAssembly.</p>
+
+<ol>
+ <li>Нам понадобится простой пример для компиляции. Скопируйте следующий код программы на Си и сохраните его в файле  <code>hello.c</code> в новой папке на вашем локальном диске:
+
+ <pre class="brush: cpp">#include &lt;stdio.h&gt;
+
+int main(int argc, char ** argv) {
+ printf("Hello World\n");
+}</pre>
+ </li>
+ <li>Теперь, используя терминал, перейдите в каталог, в котором находится ваш файл hello.c, и выполните следующую команду:
+ <pre class="brush: bash">emcc hello.c -s WASM=1 -o hello.html</pre>
+ </li>
+</ol>
+
+<p>Рассмотрим параметры, которые мы передали компилятору:</p>
+
+<ul>
+ <li><code>-s WASM=1</code> — Указывает, что мы хотим получить wasm модуль. Если не использовать этот параметр, по умолчанию Emscripten просто создает  <a href="http://asmjs.org/">asm.js</a>;</li>
+ <li><code>-o hello.html</code> — Указывает, что мы хотим, чтобы Emscripten сгенерировал HTML-страницу <code>hello.html</code> запускающую наш код, а также сам модуль wasm и код JavaScript который позволит использовать модуль в веб-среде.</li>
+</ul>
+
+<p>На этом этапе в вашем каталоге должны находится:</p>
+
+<ul>
+ <li>Бинарный код модуля wasm (<code>hello.wasm</code>)</li>
+ <li>Файл JavaScript, содержащий код связывающий нативные функции Си и JavaScript/wasm (<code>hello.js</code>)</li>
+ <li>HTML-страница для загрузки, компиляции и инициализации wasm модуля, и отображающий его вывод в браузере (<code>hello.html</code>)</li>
+</ul>
+
+<h3 id="Запуск_вашего_примера">Запуск вашего примера</h3>
+
+<p>Теперь, все что нужно чтобы запустить полученный  <code>hello.html</code> в браузере, это поддержка WebAssembly. Он включен по умолчанию в Firefox 52+, Chrome 57+ и последних версиях Opera. Также вы можете использовать модули WebAssembly в Firefox 47+, включив флаг <code>javascript.options.wasm</code> в <em>about:config</em>, или в Chrome 51+ и Opera 38+ перейдя в <em>chrome://flags</em> и включив флаг <em>Experimental WebAssembly.</em></p>
+
+<p>Если все работает как планировалось, вы должны увидеть надпись "Hello world" на открывшейся веб-странице и в JavaScript консоли вашего браузера. Поздравляем, вы только что скомпилировали программу на Си в WebAssembly и запустили ее в своем браузере!</p>
+
+<div class="note">
+<p><strong>Примечание</strong>: На самом деле, если просто открыть полученный <code>hello.html</code>, то ничего работать не будет. Подразумевается что все файлы находятся на веб-сервере и вы запускаете страницу через <code>localhost/hello.html</code>. Для этих целей можно использовать отладочный веб-сервер Emscripten. Чтобы его запустить, откройте терминал, перейдите в каталог, в котором находятся ваши файлы и выполните команду <code>emrun hello.html</code></p>
+</div>
+
+<h3 id="Использование_собственного_HTML_шаблона">Использование собственного HTML шаблона</h3>
+
+<p>Вы можете использовать собственный шаблон HTML. Давайте посмотрим, как это сделать:</p>
+
+<ol>
+ <li>
+ <p>Прежде всего, сохраните следующий код в файле hello2.c в новом каталоге:</p>
+
+ <pre class="brush: cpp">#include &lt;stdio.h&gt;
+
+int main(int argc, char ** argv) {
+ printf("Hello World\n");
+
+}</pre>
+ </li>
+ <li>
+ <p>Найдите файл  <code>shell_minimal.html</code> в вашем репозитории emsdk. Скопируйте его в подкаталог <code>html_template</code> внутри вашего нового каталога.</p>
+ </li>
+ <li>
+ <p>Теперь, используя терминал, перейдите в ваш новый каталог и выполните следующую команду:</p>
+
+ <pre class="brush: bash">emcc -o hello2.html hello2.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html</pre>
+
+ <p>В этот раз мы использовали немного другие параметры компиляции:</p>
+
+ <ul>
+ <li>Мы указали <code>-o hello2.html</code>, чтобы компилятор по прежнему генерировал необходимый JavaScript код и <code>.html</code> файл.</li>
+ <li>Также, мы указали  <code>--shell-file html_template/shell_minimal.html </code>чтобы компилятор использовал ваш шаблон для создания HTML страницы запускающей этот пример.</li>
+ </ul>
+ </li>
+ <li>
+ <p>Теперь давайте запустим этот пример. Команда, указанная выше, сгенерирует файл <code>hello2.html</code>, который будет иметь тоже содержание что и шаблон, но с некоторым кодом, добавленным в процесс загрузки сгенерированного wasm, запускающим его и т.д. Откройте его в своем браузере, и вы увидите тот же результат, что и прошлом примере.</p>
+ </li>
+</ol>
+
+<div class="note">
+<p><strong>Примечание</strong>: Вы можете указать компилятору создавать только JavaScript кода, без HTML, используя внутри флага <code>-o</code>, <code>.js</code> вместо <code>.html</code> для формата выходного файла, например <code>emcc -o hello2.js hello2.c -O3 -s WASM=1</code>. После этого вы должны создать свой собственный HTML файл с нуля. Однако так делать не рекомендуется — Emscripten теребуется большое количество связывающего кода для обработки операций выделения памяти, утечек памяти и других проблем, которые уже включены в предоставляемый шаблон. Намного легче использовать уже готовое решение, чем создавать свои собственные версии самому.</p>
+</div>
+
+<h3 id="Вызов_пользовательской_функции_определенной_в_Си">Вызов пользовательской функции, определенной в Си</h3>
+
+<p>Если у вас есть функция определенная в коде на Си, которую вы хотите по необходимости вызывать из JavaScript, то вы можете использовать для этого функцию  <code>ccall()</code> из Emscripten, и объявление <code>EMSCRIPTEN_KEEPALIVE</code> которое добавит вашу функцию в список экспортируемых функций (см. <a href="https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#why-do-functions-in-my-c-c-source-code-vanish-when-i-compile-to-javascript-and-or-i-get-no-functions-to-process">Почему функции в моем коде исчезают после компиляции и/или я получаю сообщение «Нет функций для обработки»</a>). Давайте посмотрим, как это работает.</p>
+
+<ol>
+ <li>
+ <p>Для начала сохраните следующий код в файле  <code>hello3.c</code> в новом каталоге:</p>
+
+ <pre class="brush: cpp">#include &lt;stdio.h&gt;
+#include &lt;emscripten/emscripten.h&gt;
+
+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</pre>
+
+ <p>По умолчанию, код созданный Emscripten, всегда просто вызывает функцию  <code>main()</code> , а остальные неиспользуемые функции удаляются. Добавьте определение <code>EMSCRIPTEN_KEEPALIVE</code> перед именем функции чтобы этого не происходило. Также вы должны подключить библиотеку <code>emscripten.h</code> для использования <code>EMSCRIPTEN_KEEPALIVE</code>.</p>
+
+ <div class="note">
+ <p><strong>Примечание</strong>: Мы используем блоки <code>#ifdef</code> чтобы, пример оставался рабочим если вы попытаетесь использовать C++ код. Из за различия в правилах преобразования имен между Си и Си++, этот код может сломаться, но мы написали его так, что функция будет рассматриваться как функция Си даже если вы будете использовать Си++.</p>
+ </div>
+ </li>
+ <li>
+ <p>Теперь добавьте <code>html_template/shell_minimal.html</code> в ваш новый каталог, просто для удобства. В настоящем проекте стоит размещать его в специально отпределенный каталог.</p>
+ </li>
+ <li>
+ <p>Теперь снова займемся этапом компиляции. Внутри вашего последнего каталога, используя терминал, скомпилируйте ваш Си код следующей командой. (Обратите внимание что при компиляции обязательно нужно использовать опцию NO_EXIT_RUNTIME, иначе после выполнения функции <code>main()</code>, рабочий цикл будет завершен. Это приведет, например, к вызову функции atexits и дальше будет невозможно использовать наш скомпилированный код. Другими словами это необходимо для правильной эмуляции Си.)</p>
+
+ <pre class="brush: bash">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"]'</pre>
+ </li>
+ <li>
+ <p>Если вы снова запустите пример в своем браузере, вы увидите тоже самое что и до этого!</p>
+ </li>
+ <li>
+ <p>Теперь нам нужно вызвать нашу новую функцию <code>myFunction()</code> из JavaScript. Прежде всего, добавьте {{htmlelement("button")}} как показано ниже, чуть выше первого открывающего тега <code>&lt;script type='text/javascript'&gt;</code>.</p>
+
+ <pre class="brush: html">&lt;button class="mybutton"&gt;Run myFunction&lt;/button&gt;</pre>
+ </li>
+ <li>
+ <p>Теперь добавьте следующий код в конце первого элемента {{htmlelement("script")}} (чуть выше закрывающего тега <code>&lt;/script&gt;</code>):</p>
+
+ <pre class="brush: js">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
+});</pre>
+ </li>
+</ol>
+
+<p>Это показывает как использовать <code>ccall()</code> для вызова экспортируемой функции.</p>
+
+<h2 id="Смотрите_также">Смотрите также</h2>
+
+<ul>
+ <li><a href="http://emscripten.org/">emscripten.org</a> — узнайте больше об Emscripten и разнообразии его настроек.</li>
+ <li><a href="https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#calling-compiled-c-functions-from-javascript-using-ccall-cwrap">Calling compiled C functions from JavaScript using ccall/cwrap</a></li>
+ <li><a href="https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#why-do-functions-in-my-c-c-source-code-vanish-when-i-compile-to-javascript-and-or-i-get-no-functions-to-process">Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?</a></li>
+ <li><a href="https://research.mozilla.org/webassembly/">WebAssembly on Mozilla Research</a></li>
+ <li>
+ <p><a href="/en-US/docs/WebAssembly/existing_C_to_wasm">Compiling an Existing C Module to WebAssembly</a></p>
+ </li>
+</ul>