在windows下使用zephir写php7扩展

著名的php框架phalcon为了更好的用C语言开发php扩展而发明了语言zephir,编译时zephir会被翻译成C语言然后编译成php扩展,我个人很喜欢这门语法朴素+规规矩矩+不装逼的语言。

我平时在windows下工作,目前网上搜索到的在windows下用zephir写扩展的教程都已经过时了,我花了点时间打通了一下。我环境windows 7 + VS2015 + php7.0,大体上按照官方文档来:https://github.com/phalcon/zephir/blob/master/WINDOWS.md ,我只把其中的一些需要注意的细节说一下。

1、去http://windows.php.net/download/ 的PHP 7.0 (7.0.14)的zip包,解压出来就是php-7.0.14-nts-Win32-VC14-x86文件夹,里面是编译好的php二进制。通过setx path “%path%;c:\path-to-php\”来把该目录加入环境变量,或者手动把该目录加入path环境变量,总之你的path环境变量中应该有类似这样的目录:F:\gouchaoer\cms\zephir\php-7.0.14-nts-Win32-VC14-x86

2、去http://windows.php.net/downloads/php-sdk/ 下载php-sdk-binary-tools-20110915.zip这个包解压。通过setx php_sdk “c:\path-to-php-sdk”来把该目录加入环境变量php_sdk,或者手动建立php_sdk环境变量并且把该目录加进去,注意不要自作聪明把该目录下的bin子目录加进去了(zephir调用sdk的命令的时候是%php_sdk%\bin\balabala这样来调用的),最后你的php_sdk环境变量类似:F:\gouchaoer\cms\zephir\php-sdk-binary-tools-20110915

3、下载PHP Developer Pack(NTS!),也就是http://windows.php.net/downloads/releases/ 里的php-devel-pack-7.0.14-nts-Win32-VC14-x86.zip这个包,解压里面还有一层目录php-7.0.14-devel-VC14-x86。通过setx php_devpack “c:\path-to-extracted-devpack”加入环境变量,或者手动添加,最后你的php_devpack环境变量看起来类似:F:\gouchaoer\cms\zephir\php-devel-pack-7.0.14-nts-Win32-VC14-x86\php-7.0.14-devel-VC14-x86

4、clone或者下载zephir的master分支:https://github.com/phalcon/zephir ,我们看到zephir是php写的(目前repo的最新tag是0.95版本,我直接用的master分支,目前位于75a6939的commit上,如果你按照我的方法来走不通可以试试checkout到这个commit上)。然后把zephir源码目录下的bin子目录加入path环境变量:setx path “%path%;c:\path-to-zephir\bin”,或者手动把该目录加入path环境变量,总之你的path环境变量中应该有类似这样的:F:\gouchaoer\cms\zephir\zephir\bin

5、打开开始菜单(如果你是win8我无能为力),在visual stdio2015下的visual studio tools下的windows desktop command prompts中找到”VS2015 x86本机工具命令提示符”,打开。执行 %PHP_SDK%\bin\phpsdk_setvars,你会看到REM phpsdk.bat这样的回显

OK,环境配好了,来写个zephir的hello world吧,zephir的语法请参考官方文档,给我们的扩展命名为mitsuha。

“VS2015 x86本机工具命令提示符”中进入一个空的工作目录下,这里我是F:\gouchaoer\cms\zephir\gc目录,zephir init mitsuha,然后在mitsuha目录下生成了ext子目录、mitsuha子目录和config.json文件,在mitsuha子目录下,我们建立一个taki.zep,然后里面随便写点东西:

namespace Mitsuha;
class Taki
{
	public static function kataru()
	{
		echo "what's your name?";
	}
}

然后回到”VS2015 x86本机工具命令提示符”中,注意此时你的工作目录中有config.json,执行zephir build。如果zephir官方还没有处理这个bug的话,你会遇到这个问题:

Preparing for parser compilation...
Compiling the parser...

Microsoft (R) Program Maintenance Utility Version 14.00.24210.0
Copyright (C) Microsoft Corporation.  All rights reserved.

NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 14.0\VC\BI
N\cl.exe"' : return code '0x2'
Stop.

Balabala

问题见issue:https://github.com/phalcon/zephir/issues/1366 ,官方并没有把文档适配到php7,现在我们需要一点hack。如同那个issue中的办法,在zephir源码的目录找到zephir\parser\parser\build_win32.bat,把php5的地方改成7,最后像这样:

REM Build Lemon
cl lemon.c
del parser.c parser.h scanner.c
re2c -o scanner.c scanner.re
lemon -s parser.php7.lemon
type parser.php7.c > parser.c
type base.c >> parser.c

完成再次尝试zephir build就可以成功的在mitsuha\ext\Release目录下看到php_mitsuha.dll扩展了。你上面下载的php-7.0.14-nts-Win32-VC14-x86这个php二进制里面没有默认php.ini,你需要自己建立一个php.ini,其中内容如下:

extension_dir = "ext"
extension=php_mitsuha.dll

而php_mitsuha.dll复制到F:\gouchaoer\cms\zephir\php-7.0.14-nts-Win32-VC14-x86\ext目录下就可以了。(这里看出windows版本的php二进制是绿色版无依赖的,随便copy超级方便)

然后php -m可以看到mitusha扩展已经加载了,然后写一个keisei.php内容为:

<?php
echo Mitsuha\Taki::kataru();

然后php keisei.php就可以看到输出:what’s your name?

说起zephir就不得不啰嗦一下phalcon,phalcon框架和鸟哥的yaf框架一样,都是针对纯的php框架加载导致的性能损耗,采用了C语言来写框架从而让性能接近纯的单页php应用。phalcon和yaf最开始思路相同,而且性能是一样,参考鸟哥的压测:http://www.laruence.com/2012/09/16/2791.html 。而另一种思路则是类似Swoole和phpdaemon等php-cli常驻内存的异步方案(你可以理解成php版本的nodejs),然而这种方案php-cli本身就是一个http服务器(一些地方肯定没有nginx/apache+php方案那么成熟稳定,比如https支持之类的),而且常驻内存也会导致稳定性问题(和nodejs那样某个请求挂了应用就都挂了)没有php-fpm那么耐操,而且性能和phalcon/yaf一样:http://rango.swoole.com/archives/254 。因此除了需要websocket等异步功能情况下,我认为追求性能还是yaf/phalcon方案更好。而把yaf和phalcon这两个框架进行比较的话,phalcon组件更丰富且社区更强大,我个人觉得phalcon的工作更漂亮。而后来phalcon把越来越多的组件用C扩展写,甚至还发明了zephir来缓解用C写php扩展的麻烦,让人眼睛一亮。

其实我认为yaf/zephir提高性能的关键还是把框架用C扩展的方式,这样就大大减少了框架加载的时间使性能接近纯的单页php应用,至于用C/zephir把更多的PHP基础组件替换掉能否提高性能,还是个未知数:https://github.com/phalcon/zephir/issues/694 (可以看到zephir脸都被打肿了,当然了也有很多benchmark表示zephir的确提高了性能)。有部分同学认为hello world的压测无法反映真实的业务逻辑(尤其是laravel的用户就特别喜欢说瓶颈在数据库之类的),但是我认为恰恰相反,真实的业务逻辑恰恰是命中缓存的情况最多,降低cpu消耗的同时减小处理时间是很诱人的。而zephir的另一个很大的用处我认为就是简化了我们开发C扩展的难度,你知道扩展里一堆宏一堆zend api让人很烦,而大多数情况下我只是想集中精力写逻辑业务而已。如果你想对php代码加密/限制授权,代码混淆和商用加密方案都不算完美,用zephir直接把关键代码编译成扩展可以说是雪中送炭。而且zephir还提供了Optimizer(官方比较推荐这种方式)和CBlock两种方式来让我们嵌入C代码,也提供了机制来添加别的第三方库依赖。前面说过我很喜欢zephir的朴素使用的语法,如果真的要说哪点不喜欢的话,那就是它的内建的几个面向对象的方法:https://docs.zephir-lang.com/en/latest/builtin-methods.html ,我认为zephir的string和array性质应该尽可能的像php,这几个方法最后还是会编译成面向过程的php的方法,本质上是就是语法糖。

在windows下使用zephir写php7扩展》有7个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注