Friday, May 24, 2013

How to modify the output html page to interact with Javascript - Emscripten candy!

I described in the previous post how to call your compiled code from Javascript. Well, that's cool and all, but... every time I build emscripten generates a new html file and wipes any editing I may wish to put inside the html file! To solve this I created a little utility which will combine javascript with your output html so that you can test the interaction between both in the html page. I just added the utility to the end of my build script and am set after that!


This is my build script at this point:

~/emscripten/emscripten/emcc main.cpp game.cpp ShootingScreen.cpp drawing.cpp mainmenu.cpp -o /var/www/html/archery.html -s EXPORTED_FUNCTIONS="['_imageloaded','_main']"

~/utils/htmljoin /var/www/html/archery.html javascript /var/www/html/archery2.html

The text in red, takes my emscripten output, archery.html and javascript and combines it into one file archery2.html. The contents in javascript file are inserted before the <body> tag.

My javascript file


This script code gets injected into the html output. Using this code I can call "imageloaded" which exists in my c++/c code. I found that you need to delay until you can call a function for things to load. My guess is that you could use ready() from jquery to know when you can call a c function. Also, adding jquery library links to this file might be a great idea!

Code to htmljoin utility

Save what is below to htmljoin.cpp and run "gcc  htmljoin.cpp -o htmljoin" to compile this code. It's that simple!

#include <cstdio>
#include <cstdlib>
#include <cstring>

int getFileSize( FILE * file )
{
    fseek (file , 0 , SEEK_END);
    int size = ftell (file);
    rewind (file);
    return size;
}

char * readContentsFromFile( char * filePath )
{
    FILE * file = fopen( filePath, "r" );
   
    if ( file == NULL )
    {
        printf( "ERROR: could not load file \"%s\"\n", filePath );
        return NULL;
    }

    int size = getFileSize( file );
   
    char * buffer = (char*) malloc (sizeof(char)*size + 1);   
   
    if (buffer == NULL)
    {
        printf("ERROR: error allocating memory for reading the file\n");
        fclose( file );
        return NULL;
    }

    printf( "reading %s file, %d bytes\n", filePath, size );
   
    // copy the file into the buffer:
    int result = fread( buffer, 1, size, file );
   
    buffer[size] = '\0';

    fclose( file );
   
    if (result != size)
    {
        printf("ERROR: error reading the contents of the file\n");
        free( buffer );
        return NULL;
    }

    return buffer;
}

void CreateJoinedFile( char * emscriptenHtmlFileData, char * joinHtmlFileData, FILE * outputHtmlFilePath )
{
    //find where body is in the string
    char * bodyLocation = strstr( emscriptenHtmlFileData, "<body>" );
   
    if ( bodyLocation == NULL )
    {
        printf( "ERROR: could not find the <body> tag\n" );
        return;
    }
   
    printf( "writing first piece of emscripten file...\n" );
   
    size_t toWrite = bodyLocation - emscriptenHtmlFileData;
    fwrite( emscriptenHtmlFileData, 1, toWrite, outputHtmlFilePath );

    printf( "joining files...\n" );
   
    //insert the code
    int lengthJoin = strlen( joinHtmlFileData );
    fwrite( joinHtmlFileData, 1, lengthJoin, outputHtmlFilePath );
   
    printf( "writing last piece of emscripten file...\n" );
   
    int bodyLength = strlen( bodyLocation );
    fwrite ( bodyLocation, 1, bodyLength, outputHtmlFilePath );   
}

int main( int argc, char *argv[] )
{
    char emscriptenHtmlFilePath[500], joinHtmlFilePath[500], outputHtmlFilePath[500];

    if ( argc < 4 )
    {
        printf( "you can run this program via command line with three arguments:\n" );
        printf( "arg 1 - emscripten html file\n");
        printf( "arg 2 - html file to join\n");
        printf( "arg 3 - output html file\n");
        printf( "please enter these arguments manually\n" );
        printf( "emscripten html file: " );
        gets( emscriptenHtmlFilePath );
        printf( "html file to join: " );
        gets( joinHtmlFilePath );
        printf( "output html file: " );
        gets( outputHtmlFilePath );
    }
    else
    {
        strcpy( emscriptenHtmlFilePath, argv[1] );
        strcpy( joinHtmlFilePath, argv[2] );
        strcpy( outputHtmlFilePath, argv[3] );
    }

    ///////////////////////////////////////
    // merge the files here
   
    char * emscriptenHtmlFileData = NULL, * joinHtmlFileData = NULL, * outputHtmlFileData = NULL;
    FILE * outputHtmlFile = NULL;
   
    emscriptenHtmlFileData = readContentsFromFile( emscriptenHtmlFilePath );
   
    if ( emscriptenHtmlFileData == NULL )
        goto cleanup;
       
    joinHtmlFileData = readContentsFromFile( joinHtmlFilePath );
   
    if ( joinHtmlFileData == NULL )
        goto cleanup;
       
    printf( "opening the file to write to...\n" );
   
    //open the file for writing
    outputHtmlFile = fopen( outputHtmlFilePath, "w+" );
   
    if ( outputHtmlFile == NULL )
    {
        printf( "ERROR: could not load file \"%s\"\n", outputHtmlFilePath );
        goto cleanup;
    }
   
    printf( "Creating joined file...\n" );
   
    CreateJoinedFile( emscriptenHtmlFileData, joinHtmlFileData, outputHtmlFile );
   
cleanup:

    if ( outputHtmlFile != NULL )
        fclose( outputHtmlFile );
       
    free( emscriptenHtmlFileData );
    free( joinHtmlFileData );
    free( outputHtmlFileData );
   
    return 0;
}

No comments:

Post a Comment