[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 );