php扩展开发学习笔记 5

  有许多函数在php手册里把参数或返回值类型写为mixed。那么在扩展中是如何处理的呢?所谓mixed往往就是直接解析会返回zval。

  先看参数处理,还是前面用过的zend_parse_parameters:
zval* item;
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “z”, &item);
这很简单。

  然后看返回值,返回zval可以用RETURN_ZVAL宏。和前面的RETURN_LONG之类不同的是,这个宏有3个参数。第一个参数就是一个zval*。第二个和第三个参数都是0、1值。第二个参数是表示是否在返回前复制该值;第三个参数是表示在返回前是否调用析构函数。通常的用法是RETURN_ZVAL(p_zval, 1, 0);。为什么一般要把复制zval设为1呢?这和php的内存管理有关,关于内存管理后面会说。这里大概说下,因为php的垃圾回收是基于引用计数的。如果不复制一份,在函数结束后,因为返回值也是一个zval的指针,结束后php会把这个zval的引用计数-1,在一般情况下,这就会导致释放掉不该释放掉的内存,造成错误。

 

无标题文档

  这两天下雨,阴冷的很,也没意思的很。在家宅了一天加一个上午以后,还是决定出去逛逛。逛着逛着就逛进了公园。现在是冬天,还下着雨,公园很清静,难得能看到几个人。人少了,公园显得有点空旷,也感觉大了不少。一个人在下雨的冬天逛这么“大”个公园也有一种特别的味道。
  在公园里看到一只很漂亮的猫,雪白的毛,蓝色的眼睛。这么漂亮的猫怎么也会出来流浪呢?然后,又看到一只黑白相间的猫。转了一圈回来,又一次看到了它。这时,有一对老夫妻在前面招呼它,然后它也很听话地跟了过去。我想,这或许是喂流浪猫的好心人吧。然后我走过的时候,很惊奇地看到,他们原来在给猫治病,给猫的眼睛涂药膏。动物就像小孩子,对于不舒服的治疗过程自然不会配合。于是他们就像哄小孩一样哄猫。在涂完药膏后,拿出了一些猫粮给它吃,真的像对小孩子那样。我看到这个景象后,呆了好久。
  我实在是个没心没肺的人。
  

为啥是英语……

  昨晚去逛店,在门口被一个推销剃须刀的拦住。嗯,我也是个会长胡子的男人,向我推销剃须刀也不算奇怪。那么为啥要和我说英文呢?什么shave,什么three heads……难道我戴着帽子戴着口罩就很像外国人么?

Orz 

php扩展开发学习笔记 4

zval和zvalue_value

  之前一直跳过的数组和对象,以及需要返回或者处理多种类型时,都需要了解php内部是如何保存值的。

  php内部保存值的基本单位是zval。它的C结构定义如下:

typedef struct _zval_struct {
    zvalue_value value;
    zend_uint refcount;
    zend_uchar type;
    zend_uchar is_ref;
} zval;

其中is_ref表示这个值是否是一个引用。
type表示值类型:有IS_NULL、IS_BOOL、IS_LONG、IS_DOUBLE、IS_STRING、IS_ARRAY、IS_OBJECT、IS_RESOURCE这8种。
refcount表示引用计数。
value存放这个zval的值。

  在判断一个zval的值时,可以用如下的代码:

zval *a;

if (Z_TYPE_P(a) == IS_LONG){
    …
}

  zvalue_value中保存了zval的值,它的C结构定义如下:

typedef union _zvalue_value {
    long lval;
    double dval;
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;
    zend_object_value obj;
} zvalue_value;

  这是一个union型,其中的lval、dval、str、ht、obj分别表示整数、浮点、字符串、数组、对象。

  取
得一个zval的值当然也可以直接从它的value里直接取,不过更好的办法是通过一套宏来获取。Z_BVAL、Z_LVAL_P、Z_DVAL_PP这
样的形式。都以Z_开头,后面是类型,B就是boolean,L就是long,D就是double。后面可选的_P,_PP表示指针的层次。带_P是用来
取zval*的,带_PP是用来去zval**的。这些宏返回的就是这个zval的值所对应的C类型。对于字符串,则有两组宏Z_STRVAL、
Z_STRLEN。后面当然也可以加_P和_PP。分别返回char*和字符串的长度。这些宏使用很简单,例如:

zval* a;

long n;
n = Z_LVAL_P(a);

  前面用到的Z_TYPE_P其实也是一个类似的宏,用于取得zval*的类型

应届生求职和柠檬市场

  先说下什么是柠檬市场。其实就是指信息不对称的市场。即在市场中,卖方拥有对产品质量的信息比买方更多。在极端情况下,会逐渐驱逐质量高的产品,留下质量低的产品,最终使市场瓦解。比如作为典型案例的二手车市场。卖主对自己的车了解得一清二楚,但买家却不能在一时半会里知道车的质量,也信不过卖家的一家之言。于是就只愿意按市场上的平均质量出价,这样买到好的算赚了,买到差的也不至于亏太多。但是车的质量较好的卖家就不干了,凭啥我的车就只卖这点钱,于是就退出了市场。这样市场上车的质量降低,买家愿意出的钱也降低,就这样市场上的车越来越次,最终市场就会瓦解。

  那么,这和应届生求职有啥关系呢?现在大学生多如牛毛,能力也参差不齐。每到求职的季节,用人单位往往都会收到大量的简历。为了增加自己的面试机会,许多大学生会在简历里夸大自己的能力,掩盖自己的不足。如果只有少数人这么干,那么他们或许会占些便宜。但是当多数人发现这个现象时,为了让自己不吃亏,都开始给简历注水的时候,情况就不是这样了。这时,简历的可信度降低,用人单位为了降低筛选简历的工作压力,往往就会根据平均注水程度来筛选,一些比较热门的大公司还会用计算机来海选。这时候,少数诚实的学生进入好单位的机会就会减少,同样,单位招聘到诚实的,能力强的学生的概率也会减少。但和旧车市场不同,学生不能像卖车的那样不卖了,他们还得找工作,所以这个应届生就业市场还不会瓦解,但由于单位招聘到诚实而能力强的学生的概率减少了,他们愿意出的起薪也会降低(普遍反映现在大学生素质差),最终倒霉的还是大学生。

  另外,用人单位对于应届生来说信息的透明度也不够高。但相对来说,应届生要去了解用人单位还容易些,而且应届生就业市场是个买方市场,这个问题就没有那么明显。

  对于旧车市场,后来还是有解决方案。 比如通过保证金建立赔偿机制等等,加大对不诚信行为的处罚等,增大销售劣质的成本,使它们最终被驱逐出市场。说到底就是减少信息的不对称,让买家有更多的信心。那么对于应届生就业市场是否也能有类似的办法呢?

 

 

php扩展开发学习笔记 3

取得参数

  既然是函数总要能获取参数。在php扩展里能通过zend_parse_parameters()将参数解析为一些C的对应类型。


long foo;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “l”, &foo) == FAILURE) {
RETURN_NULL();
}
会试图解析参数为整数。将值放入foo。失败的时候,比如没有参数,或参数不能解析为整数时返回FAILURE。

这里的”l”表示整数。其他如”b”,”d”,”s”分别表示布尔,浮点和字符串。资源数组对象等以后再说。

其中,布尔对应的C类型是zend_bool。其实就是0,1。浮点对应的是double。

对于字符串,则需要传入两个参数,分别用于存放字符串的值和长度。如
char *name;
int name_len;
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “s”,
&name, &name_len);
此处由zend_parse_parameters分配的内存不需要手动释放。

如果需要解析多个参数,可以如下面的例子:

long foo;
char *name;
int name_len;
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “sl”,
&name, &name_len, &foo);