I am having problems opening a user file in a C program that was compiled using emscripten (and executed via node). Take this simple cat like program:
#include <stdio.h> #define BUFSIZE 100 int main( int argc, char *argv[] ) { char *filename; FILE *file; char buf[BUFSIZE]; if (argc != 2) { fprintf (stderr, "Usage: %s <filename>\n", argv[0]); return 1; } file = fopen (argv[1], "r"); while (fgets (buf, BUFSIZE, file)) fputs (buf, stdout); fclose (file); return 0; }
I will compile this using emscripten:
% /usr/local/src/emscripten/emcc tsrc/mycat.c clang: warning: argument unused during compilation: '-nostdinc++'
It starts and expects an argument:
% node a.out.js Usage: /bin/this.program <filename>
But when I give him this argument, it barfs:
% node a.out.js somefile node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ TypeError: Function.prototype.apply: Arguments list has wrong type at Function.APPLY_PREPARE (native) at Pointer_stringify (/path/to/mycat/a.out.js:624:34) at _fopen (/path/to/mycat/a.out.js:1917:14) at Object._main (/path/to/mycat/a.out.js:2531:15) at Object.callMain (/path/to/mycat/a.out.js:2585:25) at doRun (/path/to/mycat/a.out.js:2624:20) at run (/path/to/mycat/a.out.js:2647:12) at Object.<anonymous> (/path/to/mycat/a.out.js:2663:1) at Module._compile (module.js:441:26) at Object..js (module.js:459:10)
Here's a compiled JavaScript that shows:
function Pointer_stringify(ptr, /* optional */ length) { // Find the length, and check for UTF while doing so var hasUtf = false; var t; var i = 0; while (1) { t = HEAPU8[(((ptr)+(i))|0)]; if (t >= 128) hasUtf = true; else if (t == 0 && !length) break; i++; if (length && i == length) break; } if (!length) length = i; var ret = ''; if (!hasUtf) { var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack var curr; while (length > 0) { curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); // ERROR OCCURS ON THIS LINE ret = ret ? ret + curr : curr; ptr += MAX_CHUNK; length -= MAX_CHUNK; } return ret; } var utf8 = new Runtime.UTF8Processor(); for (i = 0; i < length; i++) { assert(ptr + i < TOTAL_MEMORY); t = HEAPU8[(((ptr)+(i))|0)]; ret += utf8.processCChar(t); } return ret; }
The problematic line from the error message (line 624) is the number with String.fromCharCode.apply .
Relevant software versions:
% clang --version clang version 3.2 (tags/RELEASE_32/final) ... % node --version v0.6.15 % python --version Python 2.7.1 % /usr/local/src/emscripten/emcc --version emcc (Emscripten GCC-like replacement) 1.3.6 (commit 17da251d334ce62d633d51f874b92e19ad9dbf45) ...
In the end, I want to also upload files to the browser environment ... I know that this is a completely different ball game, with pre-loading files, etc ... now I just want the working line to work!
Updated to add: after watching https://github.com/kripken/emscripten/wiki/Filesystem-Guide I tried to preload the file and get another error:
% /usr/local/src/emscripten/emcc mycat.c --preload-file somefile ... % node a.out.js somefile node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ ReferenceError: XMLHttpRequest is not defined at...
Does this mean that I need to run it in a browser?
Updated to add:
% /usr/local/src/emscripten/emcc mycat.c -o mycat.html --preload-file README.md clang: warning: argument unused during compilation: '-nostdinc++' % open mycat.html
"Preparing ..." is displayed in the browser window, an error is displayed in the console log:
XMLHttpRequest cannot load file://localhost/path/to/mycat.data. Cross origin requests are only supported for HTTP. mycat.html:1 Uncaught Error: NETWORK_ERR: XMLHttpRequest Exception 101 mycat.html:2816 still waiting on run dependencies: mycat.html:61 dependency: fp somefile mycat.html:61 dependency: datafile_mycat.data mycat.html:61 (end of list)
... and then the last four lines - from the "dependencies still awaiting execution: mycat.htm" - are repeated every few seconds.
Do I need to pre-create these file system calls with FS on the javascript side?