系統程式的作業是要將之前寫的 C/C++ Program 轉成 JavaScript 放在網頁上面 Run,
聽起來還滿簡單的,不過卻甚是折騰,因為 Emscripten 就是個鍋。

對,沒錯,大鍋。

大到還不如直接重新寫份 JavaScript 還比較快。 _(:з」∠)_
當然啦,我的意思是假設你的 C/C++ Program 只有幾百行的話。

因為即使有 Emscripten,要做 Web Page Input 的接口,也是挺折騰的。
(如果有現成可以調的話,也是不難啦)

進入正題,來談談為什麼折騰吧,

Emscripten 安裝


首先是環境,
要選用 Linux 還是 Windows。
(我是窮學生,用不起 Mac,所以不用考慮 OSX) XD

LINUX 支線 =============================BAD END1=

Linux 我用的是之前裝在虛擬機的 Mint,
clang 和 llvm 裝好後,然後下載 Emscripten,我從官網下 portable。
編譯, 然後 clang 的動態連結庫就失效了,WTF。

這是一個剛買榔頭 (clang),開始作傢俱(Emscripten),敲第一下,榔頭就爆了的概念。

當時我的表情是這樣的。

也不是不想解決,但就是找不太到可用的 solution...

我試了第二遍,結果一樣,於是就換到 Windows 上。

畢竟不想再為難我的另一套 Linux (Antergos)。

WINDOWS 支線 ==========================GOOD END=

Windows 上要準備那些東西呢?

PythonNodeJS 還有 Emscripten Windows 的包。

Python , NodeJS 我是都剛好都有裝,所以 Emscripten 裝的還蠻順利的。

雖然安裝跑的有久,還幫你裝一些 VS 的東西,不過至少還可以用。

切到 C:\Program Files\Emscripten\emscripten\1.35.0 『版本號 1.35.0] 下可以測試。

emcc tests\hello_world.c

會跑出 a.out.js ,可以用

node a.out.js

測試。

hello, world!

LINUX 支線 =============================BAD END2=

我不死心的又回到 Mint 上搞,把 portable 刪了,改下 GitHub 的版本。

發現我忘了裝 Node,但就算少 Node , clang 照理說也不會爆才對,

( 所以 clang 爆掉應該是 portable 的鍋 )

剛開始找不到 clang 路徑,結果發現是之前裝的刪不乾淨,

在家目錄留著之前的配置文件 .emscripten ,刪了,重裝,

我折騰了一番,裝好 Node 再來一次,這次好了, clang 沒爆,換噴 llvm 版本太舊,

至少要 3.9 版,我又折騰了一番, apt-get 上 3.9 好像升不太上去,於是我無所不用其極,

找了一些旁門左道,最後還是以失敗告終。

結論,Ubuntu 除非裝比較舊的 Emscripten,不然沒辦法用,因為 llvm 升不上去。

我 Antergos 也試了,我發現 Pacman 有 Emscripten 的包,直接下載下來,clang 也順便下了,

然後我 Pacman 就爆了,WTF,就爆了 ,

是啥 openssl 的問題,我在折騰時確實有不小心升了一個 openssl 的包。

還能說甚麼呢,我 Antergos 也可能要再找個時間重裝了,因為感覺 Pacman 爛掉了,怎麼弄都弄不好

。。

Emscripten 提供輸入(stdin)

 

接下來是折騰網頁的部分,

如果直接用 Browser run,他會用 prompt() 吃 Input,

重點是如果不按 ESC(按f12好像也會) 讓 prompt() 回傳 null,他會停不下來,

不過結果是吃到資料算完會馬上輸出到 console...

這部分他主要應該是模擬 console 比較底層的架構(用 prompt 模擬 buffer 吶)。

接下來要做的是用 textarea 吃 input,並直接 output 到網頁上。

一樣在 textarea 吃到沒有時,return null。

我在 stackoverflow 的 question edit 上得到了方法,並和@46號同學 trace 八萬行大 code 生出了以下 js 。

把結果丟到 stackoverflow 上成功釣到(目前三位)同學,結果沒人知道是我寫的。QQ

  • comment run(); in the end of emscripten
// in my emscript

// shouldRunNow refers to calling main(), not run().
var shouldRunNow = true;
if (Module['noInitialRun']) {
    shouldRunNow = false;
}
//run(); // << here
// {{POST_RUN_ADDITIONS}}
  • change windows.prompt() to self def function
//result = window.prompt('Input: ');
result = areaInput();
  • add the code below in your html file to activate run() in emscripten
<script>
var message;
var point = -1;
function getArea(){
    message = document.getElementById('input').value.split('\n');
}
function areaInput(){
    if(point >= message.length - 1){
        return null;
    }
    point += 1;
    return message[point];
}
function execEmscript(){
    window.console = {
        log: function(str){
            document.getElementById("output").value += "\n" + str;
        }
    }
    getArea();
    run();
}
</script>
  • remember io textareas in your html
<textarea id="input" cols="80" rows="30"></textarea>
<textarea id="output" cols="80" rows="30"></textarea>
  • and a button
<button onclick="execEmscript();">run</button>

 

Emscripten 重新載入 js

 

Emscripten run 過第一次後有些變數會改變,

不能再 run 第二次,這時就要 reload file,讓他重新宣告/設定變數。

但有個變數 reload 也不會被重設到,那就是 Module['calledRun']。

手動重新設定 Module['calledRun'] = undefined;

然後 reload js file

這些在我的作業裡都做好了,詳情可參照 SP HW4

會不會有同學看到這篇啊(笑

創作者介紹
創作者 nobodyzxc 的頭像
nobodyzxc

Nobody's Zero

nobodyzxc 發表在 痞客邦 留言(0) 人氣()