Emscripten: С++ для web
Andrew Karpushin
+
+ +
+
+
+
+
О чем презентация
● О практическом опыте портирования приложений на С++ в веб
● О проблемах, с которыми я столкнулся в процессе
● О том какие есть ограничения, что работает, а что нет
02
CoreHard. Emscripten: С++ для web
Обо мне
● 5 лет разработки игр на С++ (PC, Xbox)
● 5 лет в serious games (Gamebryo, Unity3D)
● 4 года indie, мобильные и веб приложения/сервисы
03
CoreHard. Emscripten: С++ для web
Примеры
04
CoreHard. Emscripten: С++ для web
05
CoreHard. Emscripten: С++ для web
● Поддержка С++ runtime
● C++ standard library
● C++ exceptions
● SDL
● OpenGL
● OpenAL
Не полностью поддерживаются:
● threads
● sockets
06
CoreHard. Emscripten: С++ для web
Среда выполнения
● нет доступа к файловой системе
● никакой информации о других процессах в системе
● ограничения для HTTP запросов (CORS)
● основной цикл, в котором выполняется приложение
● float -> double
Сложности с запуском двух приложений на одной web-странице.
07
CoreHard. Emscripten: С++ для web
Вызов C++ из JavaScript
C++:
extern “C” int multiply(int a, int b) { return a*b; }
JavaScript:
console.log(Module.ccall(‘multiply’, ‘number’, [‘number’, ‘number’], [5, 6]));
Есть еще embind и WebIDL.
08
CoreHard. Emscripten: С++ для web
JavaScript из C++
Простой способ:
emscripten_run_script("alert('hi')");
EM_ASM({ window.location.reload(); });
EM_ASM_({ Module.print('the number is' + $0); }, 100);
Другой способ:
foo.h:
extern "C"
{
extern void bar(const char* text);
}
foo.js:
mergeInto(LibraryManager.library, {
bar:function (text) {...}
});
09
CoreHard. Emscripten: С++ для web
JavaScript из C++ (строки)
● EM_ASM_({
window.location.replace(Module.Pointer_stringify($0));
}, requestUrl.c_str());
● int stringPointer = EM_ASM_INT_V({
var url = window.location.href;
return allocate(intArrayFromString(url), 'i8', ALLOC_STACK);
});
const char * url = reinterpret_cast<const char *>(stringPointer);
10
CoreHard. Emscripten: С++ для web
Пример: file uploads (C++)
extern "C"
{
void uploadReplay(const uint8_t * buffer, unsigned length)
{
...
}
}
11
CoreHard. Emscripten: С++ для web
Пример: file uploads (JavaScript)
<input type="file" id="fileupload" onchange="processFile()" accept=".wotreplay"/>
function processFile(){
var file = document.getElementById('fileupload').files[0];
var reader = new FileReader();
reader.onload = function(e) {
var bytes = reader.result;
var dataPtr = Module._malloc(bytes.byteLength);
var dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, bytes.byteLength);
dataHeap.set(new Uint8Array(bytes));
Module.ccall('uploadReplay', null, ['number', 'number'], [dataHeap.byteOffset,
dataHeap.length]);
Module._free(dataHeap.byteOffset);
}
reader.readAsArrayBuffer(file);
}
12
CoreHard. Emscripten: С++ для web
Файловая система
● MEMFS
Виртуальная файловая система, но изменения не сохраняются
● NODEFS
Доступ к реальной файловой системе, но только под Node.js
● IDBFS
Позволяет хранить данные постоянно, но доступ асинхронный
13
CoreHard. Emscripten: С++ для web
IDBFS
Необходимо изменение кода для асинхронного чтениязаписи в IDBFS
До:
loadSettings();
doSomething();
После:
emscripten_idb_async_load(..., …, ..., &loadCallback, &errorCallback);
void loadCallback(void * arg, void * buffer, int bufferSize)
{
loadSettings();
doSomething();
}
void errorCallback(void * arg)
{
doSomething();
}
14
CoreHard. Emscripten: С++ для web
Сборка
● emconfigure, emmake, emcmake
● код, оптимизированный по размеру может выполняться
быстрее, чем оптимизированный по скорости
● можно компилировать в WebAssembly
○ поддерживается не всеми браузерами
● множество флагов компиляции
○ размер heap
○ экспериментальные функции (posix threads, asyncify,
emterpreter, etc.)
○ линковка с другими JavaScript библиотеками
○ линковка с виртуальной файловой системой
○ опции отладки
15
CoreHard. Emscripten: С++ для web
Отладка
16
CoreHard. Emscripten: С++ для web
Отладка
● сохранение имен функций
● подключение C++ source map
● runtime checks
○ ошибки доступа к памяти
○ переполнение стека
● stackTrace()
● логи
17
CoreHard. Emscripten: С++ для web
Другие темы
● Web Audio API
● WebGL
● WebSockets
● WebVR
● профайлинг, Emscripten tracing API
● использование в Node.js
18
CoreHard. Emscripten: С++ для web
Резюме
● С++ код может работать под web с минимальными
изменениями
● Основные проблемы:
○ файловая система
○ сеть
Для удобства приложение должно стартовать как можно раньше и
подгружать ресурсы по мере необходимости.
19
CoreHard. Emscripten: С++ для web
Полезные ссылки
● kripken.github.io
○ http://kripken.github.io/emscripten-
site/docs/getting_started/Tutorial.html
○ http://kripken.github.io/emscripten-
site/docs/api_reference/index.html
● обсуждение
○ https://groups.google.com/forum/#!forum/emscripten-discuss
● примеры
○ https://github.com/learnopengles/airhockey
○ https://github.com/inolen/quakejs
● демо
○ https://github.com/kripken/emscripten/wiki/Porting-Examples-
and-Demos
20
CoreHard. Emscripten: С++ для web
+
+
+
+
+
+
+
Спасибо за внимание
Вопросы
Andrew Karpushin andrew@wotinspector.com
+

C++ для web с помощью Emscripten

  • 1.
    Emscripten: С++ дляweb Andrew Karpushin + + + + + + +
  • 2.
    О чем презентация ●О практическом опыте портирования приложений на С++ в веб ● О проблемах, с которыми я столкнулся в процессе ● О том какие есть ограничения, что работает, а что нет 02 CoreHard. Emscripten: С++ для web
  • 3.
    Обо мне ● 5лет разработки игр на С++ (PC, Xbox) ● 5 лет в serious games (Gamebryo, Unity3D) ● 4 года indie, мобильные и веб приложения/сервисы 03 CoreHard. Emscripten: С++ для web
  • 4.
  • 5.
  • 6.
    ● Поддержка С++runtime ● C++ standard library ● C++ exceptions ● SDL ● OpenGL ● OpenAL Не полностью поддерживаются: ● threads ● sockets 06 CoreHard. Emscripten: С++ для web
  • 7.
    Среда выполнения ● нетдоступа к файловой системе ● никакой информации о других процессах в системе ● ограничения для HTTP запросов (CORS) ● основной цикл, в котором выполняется приложение ● float -> double Сложности с запуском двух приложений на одной web-странице. 07 CoreHard. Emscripten: С++ для web
  • 8.
    Вызов C++ изJavaScript C++: extern “C” int multiply(int a, int b) { return a*b; } JavaScript: console.log(Module.ccall(‘multiply’, ‘number’, [‘number’, ‘number’], [5, 6])); Есть еще embind и WebIDL. 08 CoreHard. Emscripten: С++ для web
  • 9.
    JavaScript из C++ Простойспособ: emscripten_run_script("alert('hi')"); EM_ASM({ window.location.reload(); }); EM_ASM_({ Module.print('the number is' + $0); }, 100); Другой способ: foo.h: extern "C" { extern void bar(const char* text); } foo.js: mergeInto(LibraryManager.library, { bar:function (text) {...} }); 09 CoreHard. Emscripten: С++ для web
  • 10.
    JavaScript из C++(строки) ● EM_ASM_({ window.location.replace(Module.Pointer_stringify($0)); }, requestUrl.c_str()); ● int stringPointer = EM_ASM_INT_V({ var url = window.location.href; return allocate(intArrayFromString(url), 'i8', ALLOC_STACK); }); const char * url = reinterpret_cast<const char *>(stringPointer); 10 CoreHard. Emscripten: С++ для web
  • 11.
    Пример: file uploads(C++) extern "C" { void uploadReplay(const uint8_t * buffer, unsigned length) { ... } } 11 CoreHard. Emscripten: С++ для web
  • 12.
    Пример: file uploads(JavaScript) <input type="file" id="fileupload" onchange="processFile()" accept=".wotreplay"/> function processFile(){ var file = document.getElementById('fileupload').files[0]; var reader = new FileReader(); reader.onload = function(e) { var bytes = reader.result; var dataPtr = Module._malloc(bytes.byteLength); var dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, bytes.byteLength); dataHeap.set(new Uint8Array(bytes)); Module.ccall('uploadReplay', null, ['number', 'number'], [dataHeap.byteOffset, dataHeap.length]); Module._free(dataHeap.byteOffset); } reader.readAsArrayBuffer(file); } 12 CoreHard. Emscripten: С++ для web
  • 13.
    Файловая система ● MEMFS Виртуальнаяфайловая система, но изменения не сохраняются ● NODEFS Доступ к реальной файловой системе, но только под Node.js ● IDBFS Позволяет хранить данные постоянно, но доступ асинхронный 13 CoreHard. Emscripten: С++ для web
  • 14.
    IDBFS Необходимо изменение кодадля асинхронного чтениязаписи в IDBFS До: loadSettings(); doSomething(); После: emscripten_idb_async_load(..., …, ..., &loadCallback, &errorCallback); void loadCallback(void * arg, void * buffer, int bufferSize) { loadSettings(); doSomething(); } void errorCallback(void * arg) { doSomething(); } 14 CoreHard. Emscripten: С++ для web
  • 15.
    Сборка ● emconfigure, emmake,emcmake ● код, оптимизированный по размеру может выполняться быстрее, чем оптимизированный по скорости ● можно компилировать в WebAssembly ○ поддерживается не всеми браузерами ● множество флагов компиляции ○ размер heap ○ экспериментальные функции (posix threads, asyncify, emterpreter, etc.) ○ линковка с другими JavaScript библиотеками ○ линковка с виртуальной файловой системой ○ опции отладки 15 CoreHard. Emscripten: С++ для web
  • 16.
  • 17.
    Отладка ● сохранение именфункций ● подключение C++ source map ● runtime checks ○ ошибки доступа к памяти ○ переполнение стека ● stackTrace() ● логи 17 CoreHard. Emscripten: С++ для web
  • 18.
    Другие темы ● WebAudio API ● WebGL ● WebSockets ● WebVR ● профайлинг, Emscripten tracing API ● использование в Node.js 18 CoreHard. Emscripten: С++ для web
  • 19.
    Резюме ● С++ кодможет работать под web с минимальными изменениями ● Основные проблемы: ○ файловая система ○ сеть Для удобства приложение должно стартовать как можно раньше и подгружать ресурсы по мере необходимости. 19 CoreHard. Emscripten: С++ для web
  • 20.
    Полезные ссылки ● kripken.github.io ○http://kripken.github.io/emscripten- site/docs/getting_started/Tutorial.html ○ http://kripken.github.io/emscripten- site/docs/api_reference/index.html ● обсуждение ○ https://groups.google.com/forum/#!forum/emscripten-discuss ● примеры ○ https://github.com/learnopengles/airhockey ○ https://github.com/inolen/quakejs ● демо ○ https://github.com/kripken/emscripten/wiki/Porting-Examples- and-Demos 20 CoreHard. Emscripten: С++ для web
  • 21.