首先今天遇到一个些问题,就是如何在使用的时候通过我们的扩展把lua的复合型数据传递到neko虚拟机里。
这个问题match到的几个点。
1 lua堆栈trans为Table 。
包装类型这个方案这个在我们的swig里就不在做介绍了。 我们只做大自然的搬运工就好了。
首先说明的是我们不需要做第一步,因为swig已经替我们做好了,可以直接进行第二部分。
2 需要把Lua的table 序列化成 neko VM 的 Object。
在lua的世界里是没有指针和引用,没有类型这些概念的。 比如他生成一个table大概是这样子的。
local a = { [moduName]="test", [funcName]="t", [funcParam]={1,2,3}}
我们在脚本语言里可以这样定义,但是到我们的c里面呢失灵了。首先除却预先定义好的struct这种说法不讨论。我们需要解复用,我们越过lua的堆栈操作的API直接neko VM生成在的数据结构。拆分一下API可能会有一系列的getter和setter。
value getObject();value getArray(int size);char * getObjectString(value obj, char * k);……void setObjectProb(value obj, char * k, value v) ;void setObjectInt(value obj, char * k, int v);void setObjectString (value obj, char * k , char * v);void setObjectBoolean(value obj, char * k, int v);void setObjectNumber(value obj, char * k, double v);void print(value v) ;
这些低级api 可以通过lua直接使用,通过组合这些操作,table数据我们就描述清楚了,table里怎么嵌套大致就几种。当然在使用neko VM的某些定义的时候一定要看仔细定义。比如需要的是指针或者引用,而swig有点不太care这块。
3 如何区分动态的类型。
这里有个问题就是 neko的 value 类型
typedef enum { VAL_INT = 0xFF, VAL_NULL = 0, VAL_FLOAT = 1, VAL_BOOL = 2, VAL_STRING = 3, VAL_OBJECT = 4, VAL_ARRAY = 5, VAL_FUNCTION = 6, VAL_ABSTRACT = 7, VAL_INT32 = 8, VAL_PRIMITIVE = 6 | 16, VAL_JITFUN = 6 | 32, VAL_32_BITS = 0xFFFFFFFF} val_type;
如果在纯c工程里是可以直接使用的。但是在我们的环境里是不可以使用的。比如 table 就必须是 table , 搞个tppedef 或者 void * 到这里交叉编译不通过。
local module = example.loadModule("mymodule.n", "test")print(module);example.executeModule(module);print("==============");local paramA = example.getObject();--example.test();--example.setObjectBoolean(paramA,"b",1);--example.setObjectNumber(paramA,"d",3.14);example.setObjectString(paramA,"funcName","f");local arr = example.getArray(0);example.setObjectProb(paramA,"funcParam", arr);example.setObjectString(paramA,"moduleName","test");--example.setObjectInt(paramA,"I",1000);print("-------------------------");print(example.getObjectString(paramA,"moduleName"));print(example.getObjectString(paramA,"funcName"));print(example.getObjectString(paramA,"funcParam"));print("-------------------------");example.callModuleMethod(paramA);print("call func done");print(example.getObjectString(paramA,"moduleName"));
最后来个测试结果
vm testuserdata: 0x14ba9b8add module done testuserdata: 0x14ba728==============setObjectProbString [k]=funcName [v]=f runsetObjectProb runsetObjectProbString [k]=moduleName [v]=test run-------------------------getObjectString runstring : test (4 bytes)testgetObjectString runstring : f (1 bytes)fgetObjectString runarray : size 0
越来越接近真相了。