Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save files from C to browser storage with emscripten

Tags:

emscripten

The game engine that I'm using to run my game in the browser runs lua and from my game i save files using normal fopen / write / fclose. The engine C/C++ code is compiled to JS through emscripten. What is a good way to get these file writes to end up in local storage, or some other in browser cache location? I have searched the web and looked at the documentation but information is very sparse, I have not found any clear answers to how this is supposed to work.

A previous contributor to the game engine added a js library to the emscripten build, that would override fclose to call back to javascript. But this fclose override does not seem to get called anymore, it is not included in the final .js file at all.

like image 884
Joakim Tall Avatar asked Feb 10 '19 14:02

Joakim Tall


1 Answers

Emscripten Filesystem API covers your case using IndexedDB.

Here is the Filesystem API overview. It has four types:

  1. MEMFS: A volatile, in-memory storage. This is the default filesystem type which is mounted at / at runtime.
  2. NODEFS: This uses node.js fs api, which is not your case.
  3. IDBFS: This makes use of IndexedDB and you may use it for offline storage.
  4. WORKERFS: This is intended to be used inside of a worker.

You can use IDBFS with Emscripten's own FS API (This is JavaScript-side API though). You need to mount it first in order to use it. You can achieve it by using FS.mkdir,FS.mount, and FS.syncfs. Here is a rough example in C:

#include <emscripten.h>

int main() {
    // EM_ASM is a macro to call in-line JavaScript code.
    EM_ASM(
        // Make a directory other than '/'
        FS.mkdir('/offline');
        // Then mount with IDBFS type
        FS.mount(IDBFS, {}, '/offline');

        // Then sync
        FS.syncfs(true, function (err) {
            // Error
        });
    );

    // Use fopen / write / fclose in C here.
    int off_file = fopen("/offline/any_file");
    ...

    // Don't forget to sync to make sure you store it to IndexedDB
    EM_ASM(
        FS.syncfs(function (err) {
            // Error
        });
    );
}

Here is a more detailed example from Emscripten repository.

like image 124
Bumsik Kim Avatar answered Sep 20 '22 15:09

Bumsik Kim