摘要:歡迎加入和技術(shù)交流群,群聊號碼。下面是正文如果只是想要入門的話,使用是非常簡單的。主要是通過來工作的。實(shí)際上,這塊區(qū)域不僅可以顯示文本。對于開發(fā)者來說,這是非常好的資源。
翻譯:云荒杯傾
本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。
也可以去作者的博客閱讀文章。
歡迎加入Wasm和emscripten技術(shù)交流群,群聊號碼:939206522。
如果只是想要入門Emscripten的話,使用Emscripten是非常簡單的。本教學(xué)將教會你從命令行編譯Emscripten代碼的種種步驟,以及Emscripten代碼中怎樣使用文件和使用主要的編譯優(yōu)化flag。
要事優(yōu)先首先是確保你已經(jīng)下載并且安裝好了Emscripten。根據(jù)你的操作系統(tǒng)不同,下載和安裝過程稍有不同。
Emscripten主要是通過emcc(Emscripten Compiler Frontend)來工作的。這是個命令行工具,它會調(diào)用其他編譯需要的工具,可以將它看成是標(biāo)準(zhǔn)編譯器比如gcc或者clang的命令行版本。wimdows系統(tǒng)的話,命令行中使用emcc,Linux下使用./emcc。
驗(yàn)證Emscripten第一次使用Emscripten,請先使用以下命令驗(yàn)證Emscripten是否正確安裝:
emcc -v
如果有警告發(fā)生,可能是因?yàn)槿鄙僖恍┕ぞ?,請去看這個鏈接解決
如果沒有警告或報錯,就往下看。
現(xiàn)在就可以使用Emscripten把C/C++代碼編譯成JavaScript了。
首先,寫一個待編譯為JavaScript的C文件。比如hello_world.c,像下面這樣:
#includeint main() { printf("hello, world! "); return 0; }
注:這是Emscripten提供的測試集中最簡單的一個C文件。
為了編譯這個C文件,你只需要在test目錄下打開命令行,emcc后面跟上這個文件名就行了。
emcc tests/hello_world.c
注:test目錄是Emscripten測試集的目錄。
這樣就會在test目錄下生成一個a.out.js文件,你可以使用node運(yùn)行這個a.out.js。
node a.out.js
就會在node控制臺打印出hello world!了。
如果編譯失敗,你可以在emcc tests/hello_world.c后面加個-v,也就是變成emcc tests/hello_world.c -v ,這樣呢就會有一些調(diào)試信息,你可以參考他們,找出編譯失敗的原因。生成HTML
Emscripten能為剛才輸出的那個JavaScript生成HTML文件,你可以使用-o命令指定要輸出的html文件名。
emcc tests/hello_world.c -o hello.html
在瀏覽器打開這個hello.html。你會看到,這個HTML頁面中有一塊文本區(qū)域是為了顯示C代碼中printf()函數(shù)打印的內(nèi)容。
實(shí)際上,這塊區(qū)域不僅可以顯示文本。如果你C代碼中調(diào)用了SDL的API,那么也可以在一塊canvas中顯示一個五彩斑斕的cube。比如,hello_world_cube.cpp那個測試用例就是這樣。那個測試用例的代碼是:
#include使用文件#include #ifdef __EMSCRIPTEN__ #include #endif extern "C" int main(int argc, char** argv) { printf("hello, world! "); SDL_Init(SDL_INIT_VIDEO); SDL_Surface *screen = SDL_SetVideoMode(256, 256, 32, SDL_SWSURFACE); #ifdef TEST_SDL_LOCK_OPTS EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; SDL.defaults.opaqueFrontBuffer = false;"); #endif if (SDL_MUSTLOCK(screen)) SDL_LockSurface(screen); for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { #ifdef TEST_SDL_LOCK_OPTS // Alpha behaves like in the browser, so write proper opaque pixels. int alpha = 255; #else // To emulate native behavior with blitting to screen, alpha component is ignored. Test that it is so by outputting // data (and testing that it does get discarded) int alpha = (i+j) % 255; #endif *((Uint32*)screen->pixels + i * 256 + j) = SDL_MapRGBA(screen->format, i, j, 255-i, alpha); } } if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); printf("you should see a smoothly-colored square - no sharp lines but the square borders! "); printf("and here is some text that should be HTML-friendly: amp: |&| double-quote: |"| quote: |"| less-than, greater-than, html-like tags: | | another line. "); SDL_Quit(); return 0; }
C/C++中,可以用libc庫的fopen,fclose等API來訪問文件
js運(yùn)行在瀏覽器的沙盒環(huán)境中,并不能直接訪問本地文件系統(tǒng),不過,Emscripten模擬了一個文件系統(tǒng),這樣你可以在你的C/C++代碼中繼續(xù)使用libc的API。
你想訪問的文件應(yīng)該通過preload或者embedded的方式打包到Emscripten虛擬的文件系統(tǒng)中。
測試集中,hello_world_file.cpp展示了怎么加載一個文件。測試代碼和測試文件hello_world_file.txt如下面所示:
#includeint main() { FILE *file = fopen("tests/hello_world_file.txt", "rb"); if (!file) { printf("cannot open file "); return 1; } while (!feof(file)) { char c = fgetc(file); if (c != EOF) { putchar(c); } } fclose (file); return 0; }
== This data has been read from a file. The file is readable as if it were at the same location in the filesystem, including directories, as in the local filesystem where you compiled the source. ==
下面命令是在任何編譯代碼運(yùn)行前指定一個數(shù)據(jù)文件預(yù)加載到Emscripten的虛擬文件系統(tǒng)。這個方法很有用,因?yàn)闉g覽器只能異步獲取數(shù)據(jù)的,而原生代碼(C/C++)很多都是使用的同步文件API,那么,用這個方法可以確保數(shù)據(jù)加載完成之前,編譯代碼(C/C++編譯之后的js)不會從Emscripten的虛擬文件系統(tǒng)中去取數(shù)據(jù),也就不會出錯。下面是編譯命令:
./emcc tests/hello_world_file.cpp -o hello.html --preload-file tests/hello_world_file.txt
運(yùn)行生成的HTML,就能看到hello_world_file.txt文件的內(nèi)容。
優(yōu)化代碼默認(rèn)情況下,和gcc以及clang等編譯器一樣,Emscripten生成的編譯代碼沒有經(jīng)過編譯優(yōu)化。那么,你可以在命令行參數(shù)中使用-O1,生成輕微優(yōu)化的代碼。
./emcc -O1 tests/hello_world.cpp
因?yàn)榫幾g生成a.out.js的過程實(shí)際上并不真的需要優(yōu)化,所以實(shí)際上你加不加-O1,從編譯時間(或者說編譯速度)上,你是看不出區(qū)別的。
但是真的沒區(qū)別嗎?
你可以看看生成的a.out.js文件,就能發(fā)現(xiàn)還是有區(qū)別的。-O1的優(yōu)化有一些微小的優(yōu)化并且清除了一些運(yùn)行時斷言,比如,在生成的代碼中,printf函數(shù),會被替換成put。
想編譯優(yōu)化,不僅可以用-O1,還可以用-O2,-O2優(yōu)化的程度更厲害。你可以試一下,它的編譯代碼跟-O1又有很大差別。
Emscripten 測試集Emscripten給大家提供了非常多的測試用例,幾乎覆蓋了Emscripten的所有功能。對于開發(fā)者來說,這是非常好的資源。
關(guān)于測試集的更多情況,可以點(diǎn)擊了解。
小貼士和下一步本教學(xué)告訴了你使用Emscripten的第一步,就是使用命令行編譯一個c/c++代碼為js或者HTML。為了了解更多Emscripten,給你幾個小貼士:
本站點(diǎn)還有很多高級一點(diǎn)的教程,比如,關(guān)于編譯和構(gòu)建一個項(xiàng)目,整合你的原生代碼到web環(huán)境,打包你的代碼等。
關(guān)于怎么用Emscripten,測試集是一個很好的參考的地方。比如你想了解--pre-js選項(xiàng)怎么工作,你就在測試集里面搜--pre-js,通常來說你會搜到好幾個例子。
讀一下本站的settings.js、emcc和emscripten.h的部分。
讀一下本站的FAQ。
Emscripten主題系列文章是emscripten中文站點(diǎn)的一部分內(nèi)容。
第一個主題介紹代碼可移植性與限制
第二個主題介紹Emscripten的運(yùn)行時環(huán)境
第三個主題第一篇文章介紹連接C++和JavaScript
第三個主題第二篇文章介紹embind
第四個主題介紹文件和文件系統(tǒng)
第六個主題介紹Emscripten如何調(diào)試代碼
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/51278.html
摘要:歡迎加入和技術(shù)交流群,群聊號碼。下面是正文如果只是想要入門的話,使用是非常簡單的。主要是通過來工作的。實(shí)際上,這塊區(qū)域不僅可以顯示文本。對于開發(fā)者來說,這是非常好的資源。 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。也可以去作者的博客閱讀文章。歡迎加入Wasm和emscripten技術(shù)交流群,群聊號碼:939206522。 下面...
摘要:教程之代碼可移植性與限制一翻譯云荒杯傾本文是專欄系列文章之一,更多文章請查看專欄。下面是正文代碼可移植性與限制幾乎可以編譯任何可移植的代碼到。如果標(biāo)準(zhǔn)機(jī)構(gòu)將共享狀態(tài)添加到中,支持多線程代碼將成為可能。 Emscripten教程之代碼可移植性與限制(一) 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。也可以去作者的博客閱讀文章。歡迎...
摘要:值啟用了更詳細(xì)的堆棧保護(hù)檢查,它以犧牲一些性能的代價提供更精確的。這種可以由任何類型的編碼錯誤引起,但表現(xiàn)為函數(shù)指針錯誤,因?yàn)樵谶\(yùn)行時的預(yù)期表中無法找到函數(shù)。 翻譯:云荒杯傾本文是Emscripten-WebAssembly專欄系列文章之一,更多文章請查看專欄。也可以去作者的博客閱讀文章。歡迎加入Wasm和emscripten技術(shù)交流群,群聊號碼:939206522。 調(diào)試Emscri...
閱讀 2743·2023-04-25 14:21
閱讀 1180·2021-11-23 09:51
閱讀 4025·2021-09-22 15:43
閱讀 613·2019-08-30 15:55
閱讀 1564·2019-08-29 11:28
閱讀 2450·2019-08-26 11:44
閱讀 1685·2019-08-23 18:15
閱讀 2886·2019-08-23 16:42