[NAME]
ALL.daovm.interface.embedding

[TITLE]
嵌入道虚拟机

[DESCRIPTION]


 1   一个简单的例子     
 1   一个简单的例子     
 1   一个简单的例子     

 1.1   初始化道运行环境  

在使用道库做任何事之前,DaoInit()必须被调用以初始化道运行环境。
     
   1  // 初始化道:
   2  DaoVmSpace *vmspace = DaoInit( NULL );
     
这个函数将返回一DaoVmSpace对象,该对象可用来载入道脚本或模块。 此函数可以接受一char*字符串参
数,传入的此参数应当是此程序的路径 和名称,用来确定额外的模块搜寻路径。

 1.2   载入脚本文件  

一旦你有了一个DaoVmSpace对象,你可以开始运行道脚本或载入道模块了。 如果你有一个主脚本文件,并
且你所要做的仅仅是执行这个文件,你可以简单地调用: 
     
   1  // 载入并执行 "myscript.dao":
   2  DaoVmSpace_Load( vmspace, "myscript.dao" );
     
顶层作用域的代码将被执行。
 1.3   退出道环境  

在你用完道虚拟机后,你可以调用以下函数来正确地终止道虚拟机并退出道环境。 调用这个这个函数将
会等待未完成的线程结束,也会等待垃圾回收器回收完垃圾对象, 并且释放一些内部数据结构等。 
     
   1  // 退出 Dao:
   2  DaoQuit();
     

 1.4   将这些代码放在一起  

将这些代码放在一起,嵌入道就如下面的例子简单: 
     
   1  // 初始化 Dao:
   2  DaoVmSpace *vmspace = DaoInit( NULL );
   3  // 载入运行 "myscript.dao":
   4  DaoVmSpace_Load( vmspace, "myscript.dao" );
   5  // 退出 Dao:
   6  DaoQuit();
     


 2   一个稍微高级点的例子     
 2   一个稍微高级点的例子     
 2   一个稍微高级点的例子     

在道里,每个代码文件在编译后都会被表示为一个命名空间对象, 它存有这个文件里的和一些它载入的
文件里的全局常量和变量等。 要做任何实际的事情,你一般都要用到这个命名空间对象。

 2.1   获得命名空间对象  

接着上面的例子,如果你想要调用"myscript.dao"里的某个函数, 你可以先保存DaoVmSpace_Load()所返
回的命名空间对象: 
     
   1  // 载入 "myscript.dao" 并获得命名空间对象:
   2  DaoNamespace *nspace = DaoVmSpace_Load( vmspace, "myscript.dao" );
     


 2.2   获取函数对象  

要找到你想调用的函数,使用如下代码: 
     
   1  // 查找名为 "myfunction" 的对象:
   2  DaoValue *value = DaoNamespace_FindData( nspace, "myfunction" );
   3  // 尝试将它转换为函数对象:
   4  DaoRoutine *myfunc = DaoValue_CastRoutine( value );
     
如果"myfunction"确实是个函数对象,myfunc将不会是空指针。

 2.3   获得虚拟机进程对象  

道程序都是以虚拟机进程的方式在道虚拟机上运行。 因此若要调用前面的函数,你将需要一个虚拟机进
程对象DaoProcess。 这种对象可由直接调用DaoProcess_New()生成, 但是更好的方式是从DaoVmSpace对
象获得, 这种方式更经济,更方便管理。 
     
   1  // 获得虚拟机进程对象:
   2  DaoProcess *proc = DaoVmSpace_AcquireProcess( vmspace );
     

 2.4   准备参数值  

现在假定函数"myfunction"需要一个整数作为第一个参数和一个字符串作为第二个参数。 为了调用它,
我们将需要先准备好一个道整数对象和一个道字符串对象。 这些对象都可通过它们相应的分配器函数生
成,但是更好的方式则是使用 DaoProcess类型的“工厂”方法产生。 这些方法一般以DaoProcess_New开头
。 例如,生成道整数对象和道字符串对象,我们可以用: 
     
   1  // 准备道整数对象和道字符串对象:
   2  DaoInteger *ivalue = DaoProcess_NewInteger( proc, 123 );
   3  DaoString  *svalue = DaoProcess_NewString( proc, "abc", -1 );
     
The third parameter of  DaoProcess_NewString()的第三个参数是前面C字符串的长度, 如果为负值
,该字符串是以NULL作为结束标识。

这些对象必须放在数组里才能传递给"myfunction"函数: 
     
   1  DaoValue *params[2];
   2  params[0] = (DaoValue*) ivalue;
   3  params[1] = (DaoValue*) svalue;
     
因为这些对象是有DaoProcess的方法生成的, 你也可以通过下面的以数组得方式获得这些对象: 
     
   1  // 获取最后产生的两个对象:
   2  DaoValue **params = DaoProcess_GetLastValues( proc, 2 );
     


 2.5   调用道函数  

现在我们已经可以用准备好的参数调用前面获得的函数了: 
     
   1  // 调用函数:
   2  DaoProcess_Call( proc, myfunc, NULL, params, 2 );
     
对于类方法,一个类实例对象可作为该函数的第三个参数传入。 不过它也可作为params数组的第一个元
素传入。 值得注意的是这个函数能处理重载过的函数,因此你不需要为此做任何事 (当然还是要传入正
确的参数对象)。 没有错误的情况下,这个函数将返回零,否则返回一个表示错误的整数。

 2.6   获得函数的返回值  

如果上面的函数有返回值,该返回值可通过下面的函数获得: 
     
   1  // 获得函数的返回值:
   2  DaoValue *retvalue = DaoProcess_GetReturned( proc );
     
如果函数只返回某个特定类型的值,那么你可用DaoValue_CastXXX() 之类的函数将获得的值转换到该类
型。 你也可以使用DaoValue_TryGetXXX()将它直接转换到相应的C类型。 例如,如果"myfunction"返回整
数,你可通过下面的方式获得。 
     
   1  // 获得返回的整数:
   2  daoint retint = DaoValue_TryGetInteger( retvalue );
     

 2.7   释放虚拟进程对象  

当你使用完一个虚拟进程对象后,你需要释放它。 最好的方式是将它是放回DaoVmSpace对象,以便重用。
     
   1  // 释放虚拟进程对象:
   2  DaoVmSpace_ReleaseProcess( vmspace, proc );
     
但如果你需要频繁地使用一个虚拟进程对象, 你可以保留它直到最后不需要的时候。 不过这样的话,就
有必要释放前面准备的参数了: 
     
   1  // 释放缓存的参数:
   2  DaoProcess_PopValues( proc, 2 );
     


 2.8   将这些代码放在一起  

     
   1  // 载入 "myscript.dao" 并获得命名空间对象:
   2  DaoNamespace *nspace = DaoVmSpace_Load( vmspace, "myscript.dao" );
   3  // 查找名为 "myfunction"的对象:
   4  DaoValue *value = DaoNamespace_FindData( nspace, "myfunction" );
   5  // 尝试转换为函数对象:
   6  DaoRoutine *myfunc = DaoValue_CastRoutine( value );
   7  
   8  // 获得进程对象:
   9  DaoProcess *proc = DaoVmSpace_AcquireProcess( vmspace );
  10  
  11  // 准备一个整数对象和字符串对象:
  12  DaoInteger *ivalue = DaoProcess_NewInteger( proc, 123 );
  13  DaoString  *svalue = DaoProcess_NewString( proc, "abc", -1 );
  14  // 以数组的形式获得这两个对象:
  15  DaoValue **params = DaoProcess_GetLastValues( proc, 2 );
  16  
  17  // 调用函数:
  18  DaoProcess_Call( proc, myfunc, NULL, params, 2 );
  19  
  20  // 获取函数的返回值:
  21  DaoValue *retvalue = DaoProcess_GetReturned( proc );
  22  // 获取返回的整数值:
  23  daoint retint = DaoValue_TryGetInteger( retvalue );
  24  
  25  // 释放进程对象:
  26  DaoVmSpace_ReleaseProcess( vmspace, proc );