Embedding Dao VM


 1   A Simple Example     
 1   A Simple Example     
 1   A Simple Example     

 1.1   Initializing Dao Runtime  

Before doing anything with Dao as a library, one must call DaoInit() to initialize it fir
   1  // Initialize Dao:
   2  DaoVmSpace *vmspace = DaoInit( NULL );
This function will return a DaoVmSpace object, which can be used to load Dao scripts or m
odules. It can optionally take a char* parameter, which is assumed to be the path and nam
e of the application, and is used to add additional searching paths.

 1.2   Load A Script File  

Once you have a DaoVmSpace object, you can start to run Dao scripts or load Dao modules u
sing this object. If you have a main script file and all you need to do is to run the fil
e, you can simply call:
   1  // Load and execute "myscript.dao":
   2  DaoVmSpace_Load( vmspace, "myscript.dao" );

 1.3   Finalize Dao Runtime  

After you are done with Dao, you may call the following function to make sure, Dao is pro
perly finalized (waiting for unjoined threads to finish and the garbage collector to fini
sh, and deallocating some internal data structures etc.). 
   1  // Finalize (or Quit) Dao:
   2  DaoQuit();

 1.4   Putting These Codes Together  

Putting these codes together, embedding Dao can be as simple as, 
   1  // Initialize Dao:
   2  DaoVmSpace *vmspace = DaoInit( NULL );
   3  // Load "myscript.dao":
   4  DaoVmSpace_Load( vmspace, "myscript.dao" );
   5  // Finalize (or Quit) Dao:
   6  DaoQuit();

 2   A Slightly More Advanced Example     
 2   A Slightly More Advanced Example     
 2   A Slightly More Advanced Example     

In Dao, each single script file is represented by one namespace object. And each namespac
e object has access to the public global constants and  variables defined in the files th
at this file has loaded. To do anything interesting, one must obtain the namespace object
for the file of interest.

 2.1   Obtaining The Namespace Object  

Following the above example, if you want to call a function defined in "myscript.dao" (or
in the files it has loaded), you can simple store the returned namespace object in a vari
   1  // Load "myscript.dao" and obtain the namespace object:
   2  DaoNamespace *nspace = DaoVmSpace_Load( vmspace, "myscript.dao" );

 2.2   Obtaining The Function Object  

To find the function you want to call, 
   1  // Find an object named "myfunction":
   2  DaoValue *value = DaoNamespace_FindData( nspace, "myfunction" );
   3  // Try to cast it to a function object:
   4  DaoRoutine *myfunc = DaoValue_CastRoutine( value );
If "myfunction" is indeed a function, myfunc will not be NULL.

 2.3   Obtaining A Process Object  

Now to call the function, you will need another type of object: DaoProcess, which represe
nts a virtual machine process and is responsible for executing scripts. You can directly 
call DaoProcess_New() to create a new process object, but normally the better to get a pr
ocess object is to acquire it from a DaoVmSpace object: 
   1  // Acquire a process object:
   2  DaoProcess *proc = DaoVmSpace_AcquireProcess( vmspace );

 2.4   Prepare Parameter Values  

Now suppose the function "myfunction" needs to take an integer as its first parameter and
a string as the second. To call it, we will need to prepare parameters that can be passed
to this function. The simplest way to do this is to use the data "factory" methods that a
re associated with the process type DaoProcess. Such methods are normally begin with 
DaoProcess_New. For example, to prepare an integer value and a string value, one can do,
   1  // Prepare an integer and a string:
   2  DaoInteger *ivalue = DaoProcess_NewInteger( proc, 123 );
   3  DaoString  *svalue = DaoProcess_NewString( proc, "abc", -1 );
The third parameter of DaoProcess_NewString() is the number of bytes in the C string, and
a negative value can be used to indicate the C string is NULL terminated.

To use these two new values in the parameter list to call "myfunction", you can do, 
   1  DaoValue *params[2];
   2  params[0] = (DaoValue*) ivalue;
   3  params[1] = (DaoValue*) svalue;
Or you can simply do,
   1  // Get the last two values:
   2  DaoValue **params = DaoProcess_GetLastValues( proc, 2 );
which will return last created two values in an array.

 2.5   Call The Function  

Now we are ready to call the function we obtained before with the prepared values, 
   1  // Call the function:
   2  DaoProcess_Call( proc, myfunc, NULL, params, 2 );
For class methods, a class instance object can be passed to this function as the third pa
rameter, or it can be passed as the first value of  params. Please note that, this functi
on can handle overloaded functions automatically! So you do not need to do anything for t
hat. This function will return zero on success, or other values with errors.

 2.6   Retrieve The Returned Value  

If the function returns a value, you can obtain it by, 
   1  // Obtain the returned value:
   2  DaoValue *retvalue = DaoProcess_GetReturned( proc );
If the returned value is supposed to be of certain type, you can cast it to that type by 
using one of the  DaoValue_CastXXX() functions, or directly convert it to a proper C type
by using one of the DaoValue_TryGetXXX() functions. For example, if "myfunction" returns 
an integer, you can get it by, 
   1  // Get the integer return value
   2  daoint retint = DaoValue_TryGetInteger( retvalue );

 2.7   Release The Process Object  

After you have done with the process object, you can release it back the DaoVmSpace objec
   1  // Release the process:
   2  DaoVmSpace_ReleaseProcess( vmspace, proc );
But if you want to use a process object frequently, you may simply retain it until you no
longer need it. Then you may also need to the follow function to release the cached value
   1  // Pop the cached values:
   2  DaoProcess_PopValues( proc, 2 );

 2.8   Putting These Codes Together  

   1  // Load "myscript.dao" and obtain the namespace object:
   2  DaoNamespace *nspace = DaoVmSpace_Load( vmspace, "myscript.dao" );
   3  // Find an object named "myfunction":
   4  DaoValue *value = DaoNamespace_FindData( nspace, "myfunction" );
   5  // Try to cast it to a function object:
   6  DaoRoutine *myfunc = DaoValue_CastRoutine( value );
   8  // Acquire a process object:
   9  DaoProcess *proc = DaoVmSpace_AcquireProcess( vmspace );
  11  // Prepare an integer and a string:
  12  DaoInteger *ivalue = DaoProcess_NewInteger( proc, 123 );
  13  DaoString  *svalue = DaoProcess_NewString( proc, "abc", -1 );
  14  // Get the last two values:
  15  DaoValue **params = DaoProcess_GetLastValues( proc, 2 );
  17  // Call the function:
  18  DaoProcess_Call( proc, myfunc, NULL, params, 2 );
  20  // Obtain the returned value:
  21  DaoValue *retvalue = DaoProcess_GetReturned( proc );
  22  // Get the integer return value
  23  daoint retint = DaoValue_TryGetInteger( retvalue );
  25  // Release the process:
  26  DaoVmSpace_ReleaseProcess( vmspace, proc );