Reputation: 143
I have a simple C program that needs to parse Json data. For that I have imported JSON-C library. My C code is -
#include"json.h"
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int addnumbers(int a, int b) {
FILE *fp;
char buffer[1024];
struct json_object *parsed_json;
struct json_object *name;
struct json_object *age;
struct json_object *friends;
struct json_object *friend;
size_t n_friends;
size_t i;
fp = fopen("test.json","r");
fread(buffer, 1024, 1, fp);
fclose(fp);
parsed_json = json_tokener_parse(buffer);
json_object_object_get_ex(parsed_json, "name", &name);
json_object_object_get_ex(parsed_json, "age", &age);
json_object_object_get_ex(parsed_json, "friends", &friends);
printf("Name: %s\n", json_object_get_string(name));
printf("Age: %d\n", json_object_get_int(age));
n_friends = json_object_array_length(friends);
for(i=0;i<n_friends;i++) {
friend = json_object_array_get_idx(friends, i);
// printf("%lu. %s\n",i+1,json_object_get_string(friend));
}
return n_friends;
}
Process I followed :- Compiled the library(specifically json.h file) into bit code using command-
emcc json.h -o json.bc
and then compiled my C program using -
emcc json.c -o j_plumbing.bc -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -s ENVIRONMENT='web,worker' -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0
Then together I compiled both the files to get wasm file with this command :-
emcc json.bc j_plumbing.bc -o js_plumbing.js -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -g4 -s LINKABLE=1 -s EXPORT_ALL=1 -s ENVIRONMENT='web,worker' -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0
and this is how I'm calling it from Vue file
public draw_outline() {
Module().then(myModule => {
console.log(myModule)
const result = myModule.ccall('addnumbers',
'number',
['number', 'number'],
[4, 6]);
console.log("Value from wasm file", result);
});
}
but this is the error I'm getting-
002210ee:1 Uncaught (in promise) RuntimeError: function signature mismatch
at fclose (wasm-function[524]:0x1a777)
at addnumbers (wasm-function[148]:0x6a45)
at Module._addnumbers (webpack-internal:///./src/components/js_plumbing.js:1098:4989)
at Object.ccall (webpack-internal:///./src/components/js_plumbing.js:199:628)
at eval (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/Extraction.vue?vue&type=script&lang=ts&:128:31)
at Object.Module.onRuntimeInitialized (webpack-internal:///./src/components/js_plumbing.js:1109:95)
at doRun (webpack-internal:///./src/components/js_plumbing.js:1117:140)
at run (webpack-internal:///./src/components/js_plumbing.js:1117:436)
at runCaller (webpack-internal:///./src/components/js_plumbing.js:1113:15)
at removeRunDependency (webpack-internal:///./src/components/js_plumbing.js:373:843)
Can anyone point out what i'm doing wrong here? Any help is appreciated
Upvotes: 1
Views: 1212
Reputation: 1003
If you read closely the error and the call stack, you can notice that the problem originated in the fclose()
function. A WebAssembly module generated using emscripten has its virtual file system which does not understand the local file system on your machine. Therefore, any access to local files will fail, as the fp = fopen("test.json","r");
does and it returns NULL
. This NULL
-value of fp
pointer is the reason for the error of fclose(fp)
.
Due to my inability to work with your code (sorry) I have replicated the error in a slightly different setting, but after the quick solution!
Map virtual file system of WebAssembly/emscripten to local file system using e.g. NODEFS. You can find more information about this solution in my other answer https://stackoverflow.com/a/60510997/1319478.
#include <stdio.h>
#include <emscripten.h>
#include <emscripten/bind.h>
void test_fun()
{
FILE *fp;
EM_ASM(
FS.mkdir('/temp');
FS.mount(NODEFS, {root : '.'}, '/temp'););
fp = fopen("temp/test.json", "r");
fclose(fp);
}
EMSCRIPTEN_BINDINGS(Module)
{
emscripten::function("test_fun", &test_fun);
}
This example code tries to close a file with a pointer of NULL
value.
#include <stdio.h>
#include <emscripten.h>
#include <emscripten/bind.h>
void test_fun()
{
fclose(NULL);
}
EMSCRIPTEN_BINDINGS(Module)
{
emscripten::function("test_fun", &test_fun);
}
If you compile this example with additional debug information -g
:
emcc example.cpp -o example.js --bind -s WASM_ASYNC_COMPILATION=0 -g
And then try to execute a test script node test.js
, where test.js
is as follows:
var Module = require('./example.js');
Module.test_fun();
Then, what you get is the same error:
RuntimeError: function signature mismatch
at fclose (wasm-function[32]:127)
at test_fun() (wasm-function[17]:9)
...
Upvotes: 1