PHP扩展编写方法

本方案中采用的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以加入扩展。

�$

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容