perl中的数据类型
1,perl中的数据类型(1)perl的主要数据类型 Perl本身有三种主要的数据类型: ①标量(scalar) ②数组(array) ③散列(hash) 这三种类型在perlapi中对应有三种: ①SV(Scalar Variables) ②AV(Array Variables) ③HV(Hash Variables) 这好比c/c++里面的基本类型,比如int,char,string,map,… 任何其它语言和perl进行数据交互,都要转化成perl的主要数据类型; (2的其它基本数据类型 对于任何语言,数据类型不外乎整型、浮点、字符串等,在perlapi中,其他的基本数据类型如下所示: IV:integer variables UVunsigned integer variables NVdouble variables PVstring variables SVscalar variables 相对于c/c++来说,IV相当于类型int;UV相当于类型unsigned int;NV相当于类型double;而PV相当于类型char *。 基本数据类型的定义就相当于给perl开发者提供了基本的typemaps映射关系,其他复杂的数据结构,最终都可以用整型、浮点和字符串来表示;后面会给出详细描述。 2,Scalar Variables)创建一个SV SV *sv = newSV(0);???/* no storage allocated??*/ SV *sv = newSV(10);??/* 10 (+1) bytes of uninitialised storage allocated??*/ SV允许你分配空间后,继续使用宏命令SvGROW分配空间: SvGROW(SV*,STRLEN newlen) )其他基本数据类型和SV之间的转换 如果没有创建SV,则可以使用下列七种方式直接创建SV: SV*??newSViv(IV); SV*??newSVuv(UV); SV*??newSVnv(double); SV*??newSVpv(const char*,STRLEN); SV*??newSVpvn(const char*,160)">SV*??newSVpvf(const char*,...); SV*??newSVsv(SV*); 否则已经存在SV,则需要: void??sv_setiv(SV*,IV); void??sv_setuv(SV*,UV); void??sv_setnv(SV*,double); void??sv_setpv(SV*,const char*); void??sv_setpvn(SV*,const char*,STRLEN) void??sv_setpvf(SV*,160)">void??sv_vsetpvfn(SV*,STRLEN,va_list *,SV **,I32,bool *); void??sv_setsv(SV*,SV*); 值得注意的是newSVpvf和sv_setpvf相当于常见的"sprintf"的用法,sv_vsetpvfn则相当于"vsprintf"。 当然,还可以给SV赋值PL_sv_undef,表示perl的标量为undef。 同理,如果根据SV要返回相对应的基本类型,则需要通过下面这些宏: SvIV(SV*) SvUV(SV*) SvNV(SV*) SvPV(SV*,STRLEN len) SvPV_nolen(SV*) 如果想追加一些字串在SV的后面,可以使用: void??sv_catpv(SV*,160)">void??sv_catpvn(SV*,160)">void??sv_catpvf(SV*,160)">void??sv_vcatpvfn(SV*,bool); void??sv_catsv(SV*,189)">(3)SV的检查 I检查SV的值是否为真 SvTRUE(SV*) II检查变量是否定义 首先使用: SV*??get_sv("package::varname",FALSE); 获得变量的指针SV *,然后使用宏SVOK判断: SvOK(SV*) III判断存储的是何种基本类型的数据 想知道perl认为SV里面存储的何种基本类型的数据,可以使用下列宏: SvIOK(SV*) SvNOK(SV*) SvPOK(SV*) 而真正SV里面存储的何种类型数据,需要使用下列宏: SvIOKp(SV*) SvNOKp(SV*) SvPOKp(SV*) IV获得的长度 SvCUR(SV*) SvCUR_set(SV*,I32 val) V的末尾字串的指针 SvEND(SV*) 3,Array Variables)创建一个AV 跟SV一样: AV*??newAV(); 另外,还有一种方法: AV*??av_make(I32 num,SV **ptr); )删除数组 清空数组元素 void??av_clear(AV*); 删除数组 void??av_undef(AV*); )数组元素的获取和插入 SV**??av_fetch(AV*,I32 key,I32 lval); SV**??av_store(AV*,SV* val); (4)数组的基本特性 和大多数数组的特性的定义一样,AV定义了四种方法: void??av_push(AV*,SV*); SV*???av_pop(AV*); SV*???av_shift(AV*); void??av_unshift(AV*,I32 num); 值得注意的是av_unshift本身不插入一个数组元素,只是在AV中新增加一个空位,以供av_store来添加一个元素。 (5)AV的其它特性 计算本身数组的元素的个数 I32???av_len(AV*); 增加数组本身的元素个数分配 void??av_extend(AV*,I32 key); 值得注意的是key+1的大小必须大于AV本身的元素个数,否则此函数不会做任何事情。 获取perl数组变量的指针 同SV一样: AV*??get_av("package::varname",FALSE); 4,Hash Variables)创建一个HV HV*??newHV(); )删除散列 和AV一样: void???hv_clear(HV*); void???hv_undef(HV*); )散列key/value对的获取和插入 SV**??hv_store(HV*,const char* key,U32 klen,SV* val,U32 hash); SV**??hv_fetch(HV*,I32 lval); )散列的特性 检查散列key是否存在,并删除之(hv_delete) bool??hv_exists(HV*,U32 klen); SV*???hv_delete(HV*,I32 flags); ?HE类型 Perl使用了一种特殊的结构体来保存key/value对,key是一个字符串指针(char *),而value是一个SV的指针(SV *),下面所示几种都是HE类型的用法: I32????hv_iterinit(HV*); ????????/* Prepares starting point to traverse hash table */ HE*????hv_iternext(HV*); ????????/* Get the next entry,and return a pointer to a ???????????structure that has both the key and value */ char*??hv_iterkey(HE* entry,I32* retlen); ????????/* Get the key from an HE structure and also return ???????????the length of the key string */ SV*????hv_iterval(HV*,HE* entry); ????????/* Return an SV pointer to the value of the HE ???????????structure */ SV*????hv_iternextsv(HV*,char** key,160)">????????/* This convenience routine combines hv_iternext, ???????????hv_iterkey,and hv_iterval.??The key and retlen ???????????arguments are return values for the key and its ???????????length.??The value is returned in the SV* argument */ 如果要从HE类型中获得key和value,需要使用下面这些宏: HePV(HE* he,160)">HeVAL(HE* he) HeHASH(HE* he) HeSVKEY(HE* he) HeSVKEY_force(HE* he) HeSVKEY_set(HE* he,SV* sv) 这有两个更低级的宏是定义了的,一般仅仅用作处理key,而不能当作SV *来用: HeKEY(HE* he) HeKLEN(HE* he) 散列变量的指针 HV*??get_hv("package::varname",189)">)散列的其它特性 自从perl 5.004以来,perl也支持下面的几种特性: HE*?????hv_fetch_ent??(HV* tb,SV* key,I32 lval,160)">HE*?????hv_store_ent??(HV* tb,160)">? bool????hv_exists_ent (HV* tb,160)">SV*?????hv_delete_ent (HV* tb,I32 flags,160)">SV*?????hv_iterkeysv??(HE* entry); 5,References Variables引用是一种特殊的标量类型,其值可以指向perl的任何主要数据类型。 )创建一个RV SV* newRV_inc((SV*) thing); SV* newRV_noinc((SV*) thing); )解除引用 SvRV(SV*) )RV是否是一个RV SvROK(SV*) RV的所指代的类型 SvTYPE(SvRV(SV*)) 宏SvTYPE将返回下列九种类型: SVt_IV????Scalar SVt_NV????Scalar SVt_PV????Scalar SVt_RV????Scalar SVt_PVAV??Array SVt_PVHV??Hash SVt_PVCV??Code SVt_PVGV??Glob (possible a file handle) SVt_PVMG??Blessed or Magical Scalar )面向对象 在下面这些函数或宏的定义中,xs所需要定义的类型映射经常需要用到引用中的OO概念。 SV* sv_bless(SV* sv,HV* stash); 参数sv必须是一个引用,参数stash将指定这个引用属于哪个类。 SV* newSVrv(SV* rv,const char* classname); 针对rv创建一个新的SV,如果classname存在话,则rv blessed在指定的classname上。 SV* sv_setref_iv(SV* rv,const char* classname,IV iv); SV* sv_setref_uv(SV* rv,UV uv); SV* sv_setref_nv(SV* rv,NV iv); 复制integer,unsigned integer或double三种类型到引用类型rv上,如果classname存在话,则rv blessed在指定的classname上。同理: SV* sv_setref_pv(SV* rv,PV iv); SV* sv_setref_pvn(SV* rv,PV iv,STRLEN length); 测试一个SV是否blessed在指定的class,但不能检查继承关联,可以使用: int??sv_isa(SV* sv,const char* name); 测试一个SV是否是一个引用且blessed object,可以使用: int??sv_isobject(SV* sv); 测试一个SV是否起源于指定的class,SV是一个引用或一个类名的字串,可以使用: bool sv_derived_from(SV* sv,189)">)引用计数 int SvREFCNT(SV* sv); SV* SvREFCNT_inc(SV* sv); void SvREFCNT_dec(SV* sv); 引用计数主要是perl内存的一种记录方式,如果使用了newRV_inc,那么则增加了一次引用计数,如果在XS的子程序不对new出来引用进行消亡,则perl不会自动释放这块new出来的内存,直到perl程序结束,所以使用引用计数的时候,一定要注意内存泄露(memory leak)。 针对引用计数的这种情况,可以使用下列函数来将引用的值赋值给一个最终消亡的变量: SV*??sv_newmortal() SV*??sv_2mortal(SV*) SV*??sv_mortalcopy(SV*) 值得注意的是:sv_newmortal函数是申请一个变量SV,还需要使用sv_set*来进行赋值给SV后使用。 6,Glob Variables在perl的世界里,经常看到定义了一个classname(package name)赋值给一个SV,一个stash就表示这个样子的hash,其中每个key是一个符号名字,每个value在hash table中就是一个GV。 GV常见包含了以下几种类型: Scalar Value Array Value Hash Value I/O Handle Format Subroutine )对于特定的package获取一个stash指针 HV*??gv_stashpv(const char* name,I32 create) HV*??gv_stashsv(SV*,I32 create) )对于一个引用,获取一个stashHV*??SvSTASH(SvRV(SV*)); 接着,可以做一些额外的操作,比如获得stash中package name: char*??HvNAME(HV* stash); 甚至你可以重新re-bless: SV*??sv_bless(SV*,HV* stash) )GV为了使各种各样的数据类型转换成统一的SV,使用sv_set*v即可,但是原来的数据类型将被计入,可以使用下列四种宏来查看: SvIOK_on SvNOK_on SvPOK_on SvROK_on 7,Magic VariablesMV实际上是一个struct,可能最新的perl里,struct中的成员会有所变化,但它还是一种特殊特征的SV。 )魔术变量的分配 void sv_magic(SV* sv,SV* obj,int how,const char* name,I32 namlen); )魔术变量的特性 增加magic到HV void hv_magic(HV *hv,GV *gv,int how); 从中移除magic void sv_unmagic(SV *sv,int type); )Magic Virtual Tables "MGVTBL"提供了下列五种函数: int??(*svt_get)(SV* sv,MAGIC* mg); int??(*svt_set)(SV* sv,160)">U32??(*svt_len)(SV* sv,160)">int??(*svt_clear)(SV* sv,160)">int??(*svt_free)(SV* sv,MAGIC* mg); )查看magic MAGIC* mg_find(SV*,int type); /* Finds the magic pointer of that type */ int mg_copy(SV* sv,SV* nsv,STRLEN klen); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |