JX9 Scripting Engine

An Embeddable Scripting Engine



VM Output Consumer Callback.

A VM output consumer callback is simply a host-application defined function responsible of consuming the VM output such as redirecting it (i.e: the output) to the standard output (STDOUT) or sending it back to the connected peer. The output is generated by the virtual machine during execution of the compiled program.


The VM output consumer callback must be registered after successful compilation of the target JX9 script and prior to its execution. The registration is done using a call to jx9_vm_config() with a configuration verb set to JX9_VM_CONFIG_OUTPUT.


The JX9_VM_CONFIG_OUTPUT configuration option accepts two parameters: The first parameter is a pointer to the user defined function that is responsible of consuming the VM output (The callback) and the last parameter is an arbitrary user pointer which is forwarded verbatim by the engine to the callback as its last argument.

The output consumer callback must have the following signature:


typedef int (*ProcConsumer)(const void *pOutput,unsigned int nLength,void *pUserData);


As you can see, the callback must accept three parameters. The first parameter is a pointer to the VM generated output that the callback body can safely cast to a string (const char *) (see below for a working example). Note that, if the pointer is cast-ed to a string, keep in mind that is not null terminated. The second parameter is the VM output length in bytes. The virtual machine guarantee this number is always greater than zero. The last parameter is a copy of the pointer (callback private data) passed as the second argument to the jx9_vm_config() interface.


When done, the callback must return JX9_OK. But if for some reason the callback wishes to abort processing and thus to stop program execution, it must return JX9_ABORT instead of JX9_OK.


Note that if the host application does not install any output consumer callback, then the virtual machine will automatically redirect it's output to an internal buffer. A pointer to this buffer can be extracted later after the virtual machine have finished executing the target JX9 program using a call to jx9_vm_config() with a configuration verb set to JX9_VM_CONFIG_EXTRACT_OUTPUT. But for performance reason, we recommend that the host application install it's own output consumer callback rather than waiting for the VM to finish executing the target program and extracting the output later.

Callback examples

Our first VM output consumer callback is a simple function that redirect the VM output to the Standard Output (STDOUT) using the write() system call or the libc printf() function.

static int Output_Consumer(const void *pOutput,unsigned int nOutputLen,void *pUserData)

{

   ssize_t nWr;

   nWr = write(STDOUT_FILENO,pOutput,nOutputLen);

   if( nWr < 0 ){

     /* Abort processing */

     return JX9_ABORT;

    }

    /* All done,VM output was redirected to STDOUT */

    return JX9_OK;

}


Using the libc printf(). Remember The VM output (First argument to the callback) is not null terminated.


static int Output_Consumer(const void *pOutput,unsigned int nOutputLen,void *pUserData)

{

  /*

   * Note that it's preferable to use the write() system call to display the output

   * rather than using the libc printf() which everybody now is extremely slow.

   */

    printf("%.*s",

            nOutputLen,

            (const char *)pOutput /* Not null Terminated */

          );

     /* All done,VM output was redirected to STDOUT */

     return JX9_OK;

}


A callback that send the VM output to the connected peer.


static int Output_Consumer(const void *pOutput,unsigned int nOutputLen,void *pUserData)

{

   conn_t *pConn = (conn_t *)pUserData; /* Callback private data */

   ssize_t nWr;

   /* Send output to the peer */

   nWr = write(pConn->cli_fd,pOutput,nOutputLen);

   if( nWr < 0 ){

     /* Peer hangs on us, abort processing */

     return JX9_ABORT;

   }

   /* All done, data is sent to the peer */

   return JX9_OK;

}


Now to register the callback, simply call jx9_vm_config() with a configuration verb set to JX9_VM_CONFIG_OUTPUT as follows:


jx9_vm_config(pVm,

        JX9_VM_CONFIG_OUTPUT,

        Output_Consumer, /* Output Consumer callback */

        NULL /* Callback private data */

   );


Download & Compile This C File for a working example.



Symisc Systems
Copyright © Symisc Systems