PHP Extension & Makefile 製作

PHP Extension 是什么呢?很多写PHP的工程师,或许不知道PHP Extension是怎么做出来的,其实PHP 的最底层是使用c 语言,每一句PHP 的语法,都是透过c 语言来实现,所以我们可以藉由c ,去加强PHP 的功能,让PHP 更方便使用,一个正常的PHP Extension制作时,要先编写config.m4 这个档案,虽然这个档案不难写,不过他与Makefile的格式落差很大,这里就介绍如何使用Makefile 来编译PHP Extension ,先介绍一下正常的PHP Extension编译流程,phpize会建立Makefile档案, ./configure 这个指令会自动检查相关package 是否安装

  • 建立c code 与config.m4
  • phpize (下Linux 指令phpize)
  • ./configure
  • make
  • mv modules/xxx.so /extension : 将编译出来的so档,搬到extension目录下,这样就算完成一个PHP Extension

制作php extension Makefile

基实phpize的行为就是建立Makefile, libtool 等等工具,./configure就是检查一些设定是否正常,以及路径设定,即然我都要自已写php extension了,那就跳过这两个过程吧,自已写Makefile。

  • 首先我们先使用phpize ,自动生出一个Makefile,然后再把他改成我们想要的格式。
  • phpize & mv Makefile Makefile.global : 把Makefile改成Makefile.global

修改Makefile.global成我们要的样子Makefile.global范例

  • 加入php 安装的目录PHP_DIR = /home/program/php (路径自已修改吧)
  • 将部分变数的值改到PHP_DIR ,如prefix = $(PHP_DIR),phpincludedir = $(PHP_DIR)/include/php
  • phplibdir = $(SRC_PATH)/modules :指定编译完成后,so档的路径
  • PHP_PECL_EXTENSION = extension name //(注意名称不要重覆)
  • srcdir , builddir , top_srcdir , top_builddir ,修改至当前目录,要用绝对目录

简化过后的Makefile

Makefile.global弄半天,最后终于简化完成,以后要编译php extension就方便多了,正式写一个要用来编译程式的Makefile ,你看! 下面的PHP Makefile 多么简短。

Example

SRC_PATH = $ ( shell pwd ) 
LDEF =  - DCOMPILE_DL_MyExtension 
CXXFILE = myClass . cc extension . cc 
EXTRA_CXXFLAGS = 
CXXOUTPUT =  MyExtension 
include Makefile . global 
cp : 
 sudo cp ./ modules / $ ( CXXOUTPUT ). so / home / php_extension /

make 的结果

Example

create myClass . lo 
create myClass . o 
create extension . lo 
create extension . o 
create MyExtension . la 
create MyExtension . so 
//最后产生MyExtension.so 成功

接收php 传进来的变数的方式,使用zend_parse的function,有下列两种,其中[sal,lsl]代表要接放的变数型态。

  • zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"sal",xxx,xx)
  • zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,num_args TSRMLS_CC,"lsl", xx,xx,xx,xx)
    • l : 代表long
    • s : string
    • a : array
    • b : boolean
    • d : double
  • 回传result 给php的方式有下列几种
    • RETURN_LONG : 回传long
    • RETURN_STRING : 回传字串
    • RETURN_DOUBLE : 回传倍精数
    • RETURN_BOOL : 回传boolean (true or false)

建立一个php extension function

要写一个extension function ,就是使用PHP_FUNCTION 这个function ,而传进去的第一个参数,就是function 名称,写好之后,就可以在php 里使用simple("xxx");

Example

PHP_FUNCTION ( simple ) 
{ 
 char * str = NULL ; 
 char * tmp =  new  char [ 50 ]; 
 string result =  "" ; 
 int str_len =  0 ; 
 if ( zend_parse_parameters ( ZEND_NUM_ARGS () TSRMLS_CC , 
 "s" , 
 & str ,& str_len )  == FAILURE )  { 
 RETURN_NULL (); 
 } 
 sprintf ( tmp ,  "Your input string is [%s]"  , str ); 
 result = tmp ; 
  
 delete [] tmp ; 
 RETURN_STRING ( const_cast < char *>( result . c_str ()), 1 ); 
  
}

第二个范例是function entry 中定义的add ,主要功能是将第一个参数与第二个参数做加总的功能,在php extension 中,所有的数字回偾都是使用RETURN_LONG,不需要依int ,long,float 去判断回传值,这是由于php 变数型态很自由,不用区分得这么细。

Example

PHP_FUNCTION ( add ) 
{ 
 int num_args = ZEND_NUM_ARGS (); 
 if  ( num_args !=  2 )  { 
 RETURN_LONG ( 0 ); 
 } 
 int result =  0 , int1 , int2 ; 
 if ( zend_parse_parameters ( ZEND_NUM_ARGS () TSRMLS_CC , 
 "ll" , 
 & int1 ,& int2 )  == FAILURE )  { 
 RETURN_NULL (); 
 } 
 result =  int1  +  int2 ; 
  
  
 RETURN_LONG ( result ); 
  
}

相关问题

warning: deprecated conversion from string constant to 'char*'

我升级gcc 4.2.0 后,编译就会出现这个Warning,使用gcc 3.4.6 就没事了。

第二招,碰到Warning不要停掉,在Makefile档案中,将-Werror 这个属性拿掉吧

undefined symbol:__gxx_personality_v0

因为你使用c++ 语法,但是却没有载入c++ 的library

解法:将Makefile 的CC 加上-lstdc++ ,加上这句后,编译时,会自动载入/usr/lib/libstdc++.so。

Example

CC = cc - lstdc ++

错误: Invalid library (maybe not a PHP library)的处理

这代表,php在载入so档时,找不到程序入口,c & c++的程序入口是main ,而php extension的程序入口是zend_module_entry ,但是因为我有使用到c++ 语法,c++有个特性,在编译时,会自动乱改变数及function名称。

Example

zend_module_entry MyExtension_module_entry

像这句语法,经过c++ 编译后,就可能变成MyExtension_module_entryii,结果造成找不到程序入口而报错。

解法就是多加一句extern "C"

Example

zend_module_entry MyExtension_module_entry  =  { 

} 
  
extern  "C"  { 
 ZEND_GET_MODULE ( MyExtension ) 
}

为何要加extern "C" 呢?

我们知道C++ 有overloading 的功能,一个function 可以有多种不同的参数数量,可是c++ 是怎么办到的呢,其实他在编译程式的时候,就会自动做function name 的mapping ,例如下面的例子,可是单纯的c 语言并不懂这个东西,所以当c 语言要去读取c++ 的function 时,就必需加上extern "C" ,强迫c++ 不要乱改名称,这样c语言才能正确的执行function 。

Example

int  test ( int a ){} 
int  test ( char b , char c ){} 
  
//编译后 
test ( int a )  => test_1 ( int a ) 
test ( char b ,  char c )  => test_2 ( char b ,  char c )

转载于:https://my.oschina.net/mickelfeng/blog/343420

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值