[NAME]
ALL.daovm.interface.embedding

[TITLE]
Embedding Dao VM

[DESCRIPTION]


                          
 1   A Simple Example     
                          

 1.1   Initializing Dao Runtime  

Before doing anything with Dao as a library, one must call DaoInit() to initialize it 
first:
     
   1  // Initialize Dao:
   2  DaoVmSpace *vmspace = DaoInit( NULL );
     
This function will return a DaoVmSpace object, which can be used to load Dao scripts or 
modules. It can optionally take a char* parameter, which is assumed to be the path and 
name 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 
using this object. If you have a main script file and all you need to do is to run the
file, you can simply call:
     
   1  // Load "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
properly finalized (waiting for unjoined threads to finish and the garbage collector to
finish, 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     
                                          

In Dao, each single script file is represented by one namespace object. And each
namespace object has access to the public global constants and variables defined in the
files that 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
variable,
     
   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 
represents 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 process 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 
are 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_NewMBString( proc, "abc", -1 );
     
The third parameter of DaoProcess_NewMBString() 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
parameter, or it can be passed as the first value of params. Please note that, this 
function can handle overloaded functions automatically! So you do not need to do anything
for that. 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 
object,
     
   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
values
     
   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 );
   7  
   8  // Acquire a process object:
   9  DaoProcess *proc = DaoVmSpace_AcquireProcess( vmspace );
  10  
  11  // Prepare an integer and a string:
  12  DaoInteger *ivalue = DaoProcess_NewInteger( proc, 123 );
  13  DaoString  *svalue = DaoProcess_NewMBString( proc, "abc", -1 );
  14  // Get the last two values:
  15  DaoValue **params = DaoProcess_GetLastValues( proc, 2 );
  16  
  17  // Call the function:
  18  DaoProcess_Call( proc, myfunc, NULL, params, 2 );
  19  
  20  // Obtain the returned value:
  21  DaoValue *retvalue = DaoProcess_GetReturned( proc );
  22  // Get the integer return value
  23  daoint retint = DaoValue_TryGetInteger( retvalue );
  24  
  25  // Release the process:
  26  DaoVmSpace_ReleaseProcess( vmspace, proc );