7.1. Pika 对象 PikaObj
7.1.2. 概述
对象API提供了在 C 中访问 Python 对象的一系列接口。在模块开发中使用频率最高。
对象API本身也是使用面向对象的思想设计的,这些函数的第一个入口参数都是被操作对象的指针。
一个对象由属性和方法两个部分组成,因此对象API也分为属性和方法两个部分。
对象本身的数据类型是 PikaObj,所有 Python 对象在 C 中访问时均使用这个数据类型。
/* list */
Args* list;
};
typedef struct PikaObj_t PikaObj;
PikaObj 内部维护了一个参数表,参数表中包含了属性信息、类信息、方法信息等。 注意不要直接访问 PikaObj 内部的参数表,请使用对象 API 访问 PikaObj。这是因为对象 API 作为对外接口,是长期稳定的,而内部实现则会随着内核代码的迭代经常变动,直接操作 PikaObj 内部将极大损失后向兼容性。
7.1.4. 对象属性API
这一部分 API 提供了对 Python 对象属性的访问。
PikaObj 支持整形、浮点型、字串、指针、字节串五种基本类型的属性。使用set 和 get 方法即可读写一个对象的属性。 其中,整形,浮点型,字串和字节串和 python 中的 int, float,string,bytes 一一对应,而指针型则没有对应。
对应关系表:
PikaObj 的对象是动态的,因此可以随时为对象新增新的属性(静态对象的属性在构造时确定)。
基本类型属性的 API 有如下这些:
/* set API */
int32_t obj_setInt(PikaObj* self, char* argPath, int64_t val);
int32_t obj_setPtr(PikaObj* self, char* argPath, void* pointer);
int32_t obj_setFloat(PikaObj* self, char* argPath, float value);
int32_t obj_setStr(PikaObj* self, char* argPath, char* str);
//create a bytes buff and copy data from 'src'
int32_t obj_setBytes(PikaObj* self, char* argPath, void* src, size_t size);
/* get API */
void* obj_getPtr(PikaObj* self, char* argPath);
float obj_getFloat(PikaObj* self, char* argPath);
char* obj_getStr(PikaObj* self, char* argPath);
void* obj_getBytes(PikaObj* self, char* argPath);
// get size of bytes buff
size_t obj_getBytesSize(PikaObj* self, char* argPath);
// copy the data from bytes buff to 'out_buff', return the size of memory buff
size_t obj_loadBytes(PikaObj* self, char* argPath, void* out_buff);
基本类型属性的命名方式为 obj_set[Type] 和 obj_get[Type]。
第一个输入参数为要操作的对象指针。
第二个输入参数为属性名/属性地址。
PikaObj 支持对象嵌套,可以访问子对象的属性,在访问子对象属性时,第二个参数为属性地址,在访问本对象的属性时,第二个值为属性名。
set 方法的返回值为错误码,为 0 表示无错误发生。
PikaObj 支持泛型属性,同样提供 set 方法和 get 方法。输入参数和返回值与基本类型相似。
int32_t obj_setArg(PikaObj* self, char* argPath, Arg* arg);
Arg* obj_getArg(PikaObj* self, char* argPath);
泛型属性在使用时需要转换为基本类型。
使用以下 API 可以判断泛型属性的当前类型。
ArgType arg_getType(Arg* self);
使用以下的 API 可以将泛型属性转换为基本类型。
- 判断一个属性是否存在,返回值为 1 表示存在。
int32_t obj_isArgExist(PikaObj* self, char* argPath);
- 删除一个属性
int32_t obj_removeArg(PikaObj* self, char* argPath);
返回值为错误码,为 0 表示成功。
对象方法 API 分为方法注册和方法调用两部分,方法注册部分由预编译器代理,模块开发者只需要使用方法调用 API 即可。
7.1.6. 抛出异常
可以在模块中使用 obj_setErrorCode 抛出异常,用户可以自定义异常处理方法(继续运行或停止运行)。 抛出异常通常在 C 模块的方法中使用,传入当前方法的 self 对象指针即可,errCode 设置为非零即可触发异常。 obj_setSysOut 方法常配合 obj_setErrorCode 方法使用,用于提供调试信息,该调试信息会在异常触发时显示在终端。
/* set Error Code, if the errCode is not 0, an exaption would be throw out */
void obj_setErrorCode(PikaObj* self, int32_t errCode);
void obj_setSysOut(PikaObj* self, char* str);