美文网首页我爱编程
PHP扩展编写方法

PHP扩展编写方法

作者: WebSSO | 来源:发表于2017-08-15 09:43 被阅读399次

    本方案中采用的PHP扩展方式为:

    Ø下载PHP对应版本的源码,在其中加入、生成扩展(如smsupport.so);

    Ø然后针对安装同一版本的PHP(注意,不需要是源码安装的,可以通过yum install,apt-get install安装的),将smsupport.so放置到extension_dir中;在php.ini最后一行加入extension = smsupport.so;

    Ø重启apached服务

    Ø此后,在php文件中直接调用smsupport.so提供的方法即可。

    注意点

    Ø在进行扩展及测试的过程中我们需要设置PHP的SAFE_MODE为OFF,否则可能无法完成扩展或测试。SAFE_MODE默认为OFF。

    Ø编译php扩展的环境和运行环境需要一致!

    Ø建议先使用PHP执行脚本,此时提供错误信息较为丰富。

    PHP扩展开发

    1.从http://php.net/releases/ php中下载对应目标的PHP版本;

    2.由于php依赖libxml2-dev,为此,首先通过apt-get install libxml2-dev或者yum install libxml2-dev(注libxml2-dev在不同Linux下名称不同,baidu下)

    3.解压缩1中下载的php包,进入目录,运行./configure完成配置,此时会生成编写extension所需的一些文件

    4.进入到php源码中的ext目录,执行./ext_skel --extname=smsupport,其会自动生成一系列目录及目录内的文件

    5.在ext/smsupport目录中

    a)在.c文件中找到const zend_function_entry cqwei_functions[] = {,在其后添加自己定义的函数

    注意:自动生成的为c文件,由于本扩展中要用到cpp,强行将其改为cpp,在编译时在后端加上-lstdc++,使得编译成功

    PHP_FE(testadd,NULL)/*For testing, remove later. */

    PHP_FE(dcsSM2Verify,arg_dcsSM2Verify)

    PHP_FE(dcsSM4Decrypt,arg_dcsSM4Decrypt)

    注意点:

    ü将PHP_FE的名称改成自己的函数,可以同时包含多个;

    ü如果PHP_FE中包含的函数需要参数,则应加入参数信息,如arg_Verify,其中arg_Verify包含4个参数,arg_Decrypt包含2个参数。

    nZEND_BEGIN_ARG_INFO_EX(arg_Verify,

    0, 0, 1)

    ZEND_ARG_INFO(0,user)

    ZEND_ARG_INFO(0,pubKey)

    ZEND_ARG_INFO(0,ticket)

    ZEND_ARG_INFO(0,sig)

    ZEND_END_ARG_INFO()

    nZEND_BEGIN_ARG_INFO_EX(arg_Decrypt,0, 0, 1)

    ZEND_ARG_INFO(0,key)

    ZEND_ARG_INFO(0,cipher)

    ZEND_END_ARG_INFO()

    b)PHP_FUNCTION(testadd)在定义自定义函数testadd的函数体,如下所示为最简单的内容

    PHP_FUNCTION(testadd)

    {

    zend_printf("testadd00");

    }

    c)PHP_FUNCTION(Verify),稍微复杂,因为有参数和返回值,示例如下

    PHP_FUNCTION(Verify)

    {

    char * user;

    char * pubKey;

    char* ticket;

    char * sig;

    intuserLen,pubKeyLen,ticketLen,sigLen;

    charpubKeyArray[64];

    if(zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC,"ssss",&user,&userLen,&pubKey,&pubKeyLen,&ticket,&ticketLen,&sig,&sigLen)== FAILURE)

    {//解析参数,参数为4个char *,s表示char

    *,其他格式见下文中的表格

    RETURN_FALSE;

    return;

    }

    if(pubKeyLen != 128 || sigLen !=64)

    {

    zend_printf("the sm2 parameter isincorrect\n");

    RETURN_FALSE;

    return;

    }

    CECCPublicKey *verify = new CECCPublicKey();

    loadHexStr(pubKey,(unsigned char *)pubKeyArray,64);

    if(verify->SetPublicKey((constunsigned char*)pubKeyArray, 64) == 0)

    {

    zend_printf("the public key isincorrect\n");

    delete verify;

    RETURN_FALSE;//表示返回false

    return;

    }

    if(verify->VerifyMessage((constunsigned char *)ticket, ticketLen, (const unsigned char *)sig, sigLen, (constchar *)user, userLen) != 1)

    {

    zend_printf("the signature is incorrect\n");

    delete verify;

    RETURN_FALSE;

    return;

    }

    delete verify;

    RETURN_TRUE;//表示返回true

    return;

    }

    d)char *plain = emalloc(cipherLen);

    efree (plain);//动态分配内存和释放

    e)返回string变量RETVAL_STRINGL(plain, cipherLen, 1); plain为char *,cipherLen为长度

    f)在.h文件中加入如下内容

    PHP_FUNCTION(testadd);

    PHP_FE(Verify);

    PHP_FE(Decrypt);

    g)在php源码/ext/smsupport下编译:cc -fpic -DCOMPILE_DL_SMSUPPORT=1 -I /usr/local/include -I../ -I../../main -I ../.. -I ../../TSRM -I ../../Zend -c smsupport.cppEllipticCurve.cpp sm3hash.cpp Mpi.cpp SMS4.cpp -lstdc++ -fpermissive-Wwrite-strings

    其中除smsupport.cpp外为正常的cpp文件

    h)在php源码/ext/smsupport下链接:cc -shared -L /usr/local/lib -rdynamic -o smsupport.so *.o -lstdc++

    部署示例

    1.在CentOS上搭建php+apache

    a)Yum install php

    b)Yum install httpd

    c)Service httpd start

    2.配置php

    a)将上述生成的so文件(如smsupport.so)放置到extension_dir目录中,extension_dir路径可通过echo phpinfo()获取

    b)Find / -name “php.ini”,加入extension

    cqwei.so;(在较为靠后的位置加入)

    c)Service httpd start

    d)在php中直接调用方法即可

    细节介绍

    Øzend_parse_parameters

    n如if(zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC,"ssss",&user,&userLen,&pubKey,&pubKeyLen,&ticket,&ticketLen,&sig,&sigLen)== FAILURE)

    nZEND_NUM_ARGS()告诉Zend引擎要取得的参数的信息

    nTSRMLS_CC用来确保线程安全

    n返回值将被检查是SUCCESS还是FAILURE。

    u通常情况下,zend_parse_parameters()将返回SUCCESS;

    u然而,如果调用脚本试图传入太多或太少的参数,或者传入的参数不能被转为适当的类型,Zend会自动输出一条错误信息并优雅地将控制权还给调用脚本

    n本例指定s表明此函数期望只传入一个参数,而且该参数应该被转为string数据类型并装入通过地址传入的char*变量。

    n注意,还有一个int变量通过地址被传入zend_parse_parameters()。这使Zend引擎提供字符串的字节长度,如此二进制安全的函数不再需要依赖strlen(name)确定字符串的长度。实际上使用strlen(name)甚至得不到正确的结果,因为name可能在字符串结束之前包含一个或多个NULL字符。

    n再比如if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|b", &a,&b, &return_long) == FAILURE) {

    u这次你的数据类型字符串读起来像:“我要一个long(l),一个double(d)”。

    u下一个管道字符表示其余的参数是可选的。如果函数调用时没有传入可选参数,那么zend_parse_parameters()将不会改变传给它的对应变量。

    lb是用于Boolean。

    u数据类型字符串后面的是a、b和return_long,它们按地址传递,这样zend_parse_parameters()可以将值装入它们。

    u警告:在32位平台中经常不加区分地使用int和long,但是,当你的代码在64位硬件上编译时,在本该使用一个的地方使用另一个是很危险的。所以记住要把long用于整型,把int用于字符串的长度。

    Ø表1显示不同的类型和对应的字母代码,以及可用于zend_parse_parameters()的C类型:

    类型代码变量类型

    Booleanbzend_bool

    Longllong

    Doubleddouble

    Stringschar*, int

    Resourcerzval*

    Arrayazval*

    Objectozval*

    zvalzzval*

    n你可能立刻注意到表1中的最后四个类型都是zval*。待会儿你将看到,PHP中实际使用zval数据类型存储所有的用户空间变量。三种“复杂”数据类型,资源、数组和对象,当它们的数据类型代码被用于zend_parse_parameters()时,Zend引擎会进行类型检查,但是因为在C中没有与它们对应的数据类型,所以不会执行类型转换。

    Ø返回值

    n返回值的设置方法,网上大多数是错误的,可以借鉴ext目录下其他的扩展。

    mcrypt安装

    Ø首先安装mcrypt:http://blog.csdn.net/zy112289/article/details/52840062

    l先安装Libmcrypt

    #tar -zxvf libmcrypt-2.5.8.tar.gz

    #cd libmcrypt-2.5.8

    #./configure

    #make

    #make install说明:libmcript默认安装在/usr/local

    l安装mhash

    #tar -zxvf mhash-0.9.9.9.tar.gz

    #cd mhash-0.9.9.9

    #./configure

    #make

    #make install

    l安装mcrypt

    #tar -zxvf mcrypt-2.6.8.tar.gz

    #cd mcrypt-2.6.8

    #LD_LIBRARY_PATH=/usr/local/lib ./configure//注意,在一行输入

    #make

    #make install

    Ø安装phpize: yum install php-devel

    Ø编译、安装mcrypt

    ncd php-5.3.3/ext/mcrypt/

    nphpize

    n./configure --with-php-config=/usr/bin/php-config

    nmake && make install

    n提示:Installing shared extensions:/usr/lib64/php/modules/,说明安装成功

    n在php.ini中加入extension = mcrypt.so以加入扩展。

    �$

    相关文章

      网友评论

        本文标题:PHP扩展编写方法

        本文链接:https://www.haomeiwen.com/subject/xkrmrxtx.html