加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl中的数据类型

发布时间:2020-12-15 20:58:15 所属栏目:大数据 来源:网络整理
导读:1,perl中的数据类型 ( 1 ) perl 的主要数据类型 Perl本身有三种主要的数据类型: ①标量(scalar) ②数组(array) ③散列(hash) 这三种类型在perlapi中对应有三种: ①SV(Scalar Variables) ②AV(Array Variables) ③HV(Hash Variables) 这好比c/c++里面的
1,perl中的数据类型

1perl的主要数据类型

Perl本身有三种主要的数据类型:

①标量(scalar)

②数组(array)

③散列(hash)

这三种类型在perlapi中对应有三种:

①SV(Scalar Variables)

②AV(Array Variables)

③HV(Hash Variables)

这好比c/c++里面的基本类型,比如int,char,string,map,…

任何其它语言和perl进行数据交互,都要转化成perl的主要数据类型;

(2的其它基本数据类型

对于任何语言,数据类型不外乎整型、浮点、字符串等,在perlapi中,其他的基本数据类型如下所示:

IVinteger 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)">(3SV的检查

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来添加一个元素。

(5AV的其它特性

计算本身数组的元素的个数

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 Variables

MV实际上是一个struct,可能最新的perl里,struct中的成员会有所变化,但它还是一种特殊特征的SV。

)魔术变量的分配

void sv_magic(SV* sv,SV* obj,int how,const char* name,I32 namlen);

)魔术变量的特性

增加magicHV

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读