Symisc Systems

Libcox Programming in 3 Minutes or Less


Star Follow @symisc

Here is what you do to start experimenting with Libcox without having to do a lot of tedious reading and configuration.

Download The Code

Get a copy of the last public release of Libcox. Visit the download page for additional information. The following are Some C/C++ samples to start experimenting with:


Introduction to the command Execution interfaces (CEI)

Below is a simple C program that demonstrates how to use the Command Execution C/C++ interface to Libcox.


    #include "libcox.h"
	int main(int argc, char **argv){
		
		libcox *pHandle;            /* Libcox handle */
		libcox_value *pResult;     /* Return value of the last executed command */
		
		const char *zValue;           /* Cast the 'libcox_value' to a string */
		int rc;
	
		/* Obtain a new libcox handle*/
		rc = libcox_init(&pHandle);
		if( rc != LIBCOX_OK ){
			/* Handle error */
			return -1;
		}

		/* Execute the simplest command - uname: Get the underlying OS info (name, version, etc.) */
		rc = libcox_exec(pHandle,&pResult,"uname",-1);
		if( rc != LIBCOX_OK ){ /* Handle error */	}
		
		
		/* Get as a string representation and output the result */
		zValue = libcox_value_to_string(pResult,0);
		/* Output */
		printf("OS Info: %s\n\n",zValue); /* Should output something similar to: Windows 8.1 x64 localhost Build 85746... */

		/* Destroy the libcox_value */
		libcox_exec_result_destroy(pHandle,pResult);
		
		/* Finally, release the libcox handle */
		libcox_release(pHandle);
	}
	
Here in this example, we executed a simple command: uname which return information (name, version, ...) about the underlying operating system. An application that wants to use Libcox will typically uses the following set of interfaces with their optional components:

You may pass additional number of arguments to a given command. For that you may use libcox_exec_fmt() which is a work-alike of the "printf()" family of functions from the standard C library which is used to execute a small formatted string as follows with the chdir command:

    #include "libcox.h"
	int main(int argc, char **argv){
		
		libcox *pHandle;            /* Libcox handle */
		libcox_value *pResult;     /* Return value of the last executed command */
		
		int result; /* Boolean return value of the 'chdir' command */
		int rc;
		
		const char *zDir = "/var/log/"; /* New working directory*/
	
		/* Obtain a new libcox handle */
		rc = libcox_init(&pHandle);
		if( rc != LIBCOX_OK ){	/* Handle error */ return -1;	}

		/* Change the working directory */
		rc = libcox_exec_fmt(pHandle,&pResult,"chdir %s",zDir);
		if( rc != LIBCOX_OK ){ /* Handle error */	}
		
		/* Return value of chdir */
		result = libcox_value_to_bool(pResult);
		if( !result ){
			puts("Error while changing directory");
		}else{
			printf("New working directory: %s\n",zDir); /* may be verified via the getcwd command: http://libcox.net/cmd/getcwd.html */
		}
		
		/* Destroy the libcox_value */
		libcox_exec_result_destroy(pHandle,pResult);
		
		/* Finally, release the libcox handle */
		libcox_release(pHandle);
	}
	


Working with arrays

Libcox is shipped with a multitude of very useful commands that return a libcox_value of type array. That is, two or more entries are returned from a single command call. Some of these commands are: ls, stat, glob, getdate and many more. A typical usage when dealing with commands that return an array should look like this;


#include "libcox.h"
int main(int argc, char **argv){
	libcox *pHandle;            /* Libcox handle */
	libcox_value *pResult;      /* Return value of the last executed command */
	libcox_value *pEntry;       /* Array entries */
	int rc;
	
	const char *zDir = argc > 1 ? argv[1] /* User supplied directory */ : "./" /* current working diretcory */;
	/*
	 * You could use here the 'isdir' command to make sure that zDir is a valid directory.
	 * libcox_exec_fmt(pHandle,&pResult,"isdir '%s'",zDir)
	 * http://libcox.net/cmd/isdir.html
	 */
	puts(zBanner);

	/* Obtain a new libcox handle */
	rc = libcox_init(&pHandle);
	if( rc != LIBCOX_OK ){
		Fatal(0,"Out of memory");
	}
	
	/* List all entries within this directory using the ls command: http://libcox.net/cmd/ls.html */
	rc = libcox_exec_fmt(pHandle,&pResult,"ls '%s'",zDir); /*Don't forget the single quotes around 'zDir' */
	if( rc != LIBCOX_OK ){
		/* Seriously? */
		Fatal(pHandle,0);
	}
	if( libcox_value_is_array(pResult) ){
		if( argc > 1 ){
			/* Change the working directory so we could stat on items */
			libcox_exec_fmt(pHandle,NULL/*We do not need command return value*/,"chdir '%s'",zDir);
		}
		/* Iterate over the array which hold zDir entries */
		while( (pEntry = libcox_array_next_elem(pResult)) != NULL ){
			/* Get the file name */
			const char *zEntry = libcox_value_to_string(pEntry,NULL);
			/*
			 * You could use here the 'isfile' command to make sure that zDir is a valid directory.
			 * libcox_exec_fmt(pHandle,&pResult,"isfile '%s'",zEntry)
			 * http://libcox.net/cmd/isfile.html
			 */
			libcox_value *pStat;

			/* Get the file size, access time, etc. using the stat command: http://libcox.net/cmd/stat.html  */
			rc = libcox_exec_fmt(pHandle,&pStat,"stat '%s'",zEntry); /*Don't forget the single quotes around 'zEntry' */
			if( rc != LIBCOX_OK ){
				/* Seriously? */
				Fatal(pHandle,0);
			}
			if( libcox_value_is_array(pStat) ){
				libcox_int64 nSize;  /* File size */
				libcox_int64 aTime;  /* Access time */
				const char *zSize;   /* Presentable nSize (i.e 2GB, 563MB, etc) */
				const char *zTime;   /* Presentable time format */
				libcox_value *pSize,*pAccess; /* stat() fields */

				/* Get the file size */
				pSize = libcox_array_fetch_by_key(pStat,"size",-1);
				nSize = libcox_value_to_int64(pSize); /* File size in bytes */

				/* File last access */
				pAccess = libcox_array_fetch_by_key(pStat,"atime",-1);
				aTime = libcox_value_to_int64(pAccess); /* File last access since the UNIX epoch */

				/* Make all the thing presentable
				 * 
				 * Formatted nSize (i.e 2GB, 563MB, etc). Note the "qd" format which mean
				 * that we expect a quad number (64bit).
				 *
				 */
				libcox_exec_fmt(pHandle,&pSize,"size_format %qd",nSize); 
				zSize = "";
				if( libcox_value_is_string(pSize) ) {
					zSize = libcox_value_to_string(pSize,NULL);
				}
				/* Obtain a string representation of the file access timestamp */
				libcox_exec_fmt(pHandle,&pAccess,"date c %qd",aTime); /* http://libcox.net/cmd/date.html */
				zTime = "";
				if( libcox_value_is_string(pAccess) ) {
					zTime = libcox_value_to_string(pAccess,NULL);
				}
				/* Output */
				printf("%s\t\t%s\t\t%s\n",zEntry,zSize,zTime); /* You should see something like that: intel.xdk 166MB 2014-11-23T12:45:00+0000 */

				/* Release pSize and pAccess used in the last two libcox_exec_fmt() */
				libcox_exec_result_destroy(pHandle,pSize);
				libcox_exec_result_destroy(pHandle,pAccess);
			}
			/* Release pStat */
			libcox_exec_result_destroy(pHandle,pStat);
		} /* while(;;) */

	}else{
		Fatal(pHandle,"Expected an array!");
	}

	libcox_exec_result_destroy(pHandle,pResult);
	/*
	 * List all PDF files within this directory using the glob command:  http://libcox.net/cmd/glob.html
	 *
	 * Note that we'll use a walker callback to list all array entries instead of manually iterating over the elements.
	 * http://libcox.net/c_api/libcox_array_walk.html
	 *
	 */
	rc = libcox_exec_fmt(pHandle,&pResult,"glob *.pdf '%s'",zDir); /*Don't forget the single quotes around 'zDir' */
	if( rc != LIBCOX_OK ){
		/* Seriously? */
		Fatal(pHandle,0);
	}
	if( libcox_value_is_array(pResult) ){
		struct array_rend sRend = { 1 , 0 };

		printf("\nTotal number of PDF files: %u\n",libcox_array_count(pResult));
		/* Apply the walker callback */
		libcox_array_walk(pResult,array_render,(void *)&sRend);
	}

	/* All done, clean up */
	libcox_exec_result_destroy(pHandle,pResult);
	/* Release the libcox handle */
	libcox_release(pHandle);
}
As you can see, the workflow is typically the same as working with standard commands except that we added the very few interfaces that deals with arrays:


Useful Links to Start with

As you can see, Libcox is very easy to learn, even for new programmer. Here is some useful links to start with: