php教程 php手册 [原]【原创】PHP扩展开发入门

[原]【原创】PHP扩展开发入门

Jun 06, 2016 pm 08:13 PM
php 시작하기 원래의 개발하다 확장하다

PHP 扩展开发入门 作者:wf (360电商技术组) 在我们编写自己的第一个php扩展之前,先了解一下php的整体架构和运行机制。 php 的架构如图1所示。其中一个重要的就是SAPI(服务器端应用编程端口),它使得PHP可以和其他应用进行数据交互,把外部错综复杂的外




PHP扩展开发入门

作者:wf (360电商技术组)

在我们编写自己的第一个php扩展之前,先了解一下php的整体架构和运行机制。


    php的架构如图1所示。其中一个重要的就是SAPI(服务器端应用编程端口),它使得PHP可以和其他应用进行数据交互,把外部错综复杂的外部环境进行抽象化,为内部的php提供一套固定和统一的接口,使得php自身不受外部影响,保持一定的独立性。常见的SAPI有CGI,FastCGI,Shell的CLI,apache的mod_php5,IIS的ISAPI。

另外一个非常重要就是ZendEngine。Zend Engine是官方提供的PHP实现的核心,提供了语言实现上的基础设施,其他比较知名的还有facebook的hiphop实现。例如PHP的语法实现,脚本的编译运行环境,扩展机制以及内存管理等。我们在后面编写php扩展时,也将基于Zend Engine。

PHP3时代还是采用边解释边执行的运行方式,这种方式运行效率很受影响,其次代码整体耦合度比较高,可扩展性也不够好。因此随着php在web应用开发中的普及,于是ZeevSuraski和Andi Gutmans决定重写代码以解决这两个问题,最终他们俩把该项技术的核心引擎命名为Zend Engine 。

Zend Engine最主要的特性就是把PHP的边解释边执行的运行方式改为先预编译(Compile),再执行(Execute)。这两者的分开给 PHP 带来了革命性的变化:执行效率大幅提高。由于实行了功能分离,降低了模块间耦合度,可扩展性也大大增强。

目前PHP的实现和Zend Engine之间的关系非常紧密,例如很多PHP扩展都是使用的Zend API,而Zend正是PHP语言本身的实现,PHP只是使用Zend这个内核来构建PHP语言的,而PHP扩展大都使用Zend API,这就导致PHP的很多扩展和Zend引擎耦合在一起了,后来才有PHP核心开发者就提出将这种耦合解开的建议。不过下面我们还下面在Zend Engine的基础上开始编写我们第一个简单的php扩展。

1.配置文件

每一个PHP扩展都至少需要一个配置文件和一个源文件。配置文件用来告诉编译器应该编译哪几个文件,以及编译本扩展是否需要的其它库文件。

在php源码文件夹的ext目录下创建一个新的文件,扩展的名字取作myfirst。然后在这个目录下创建一个config.m4文件,并输入以下内容:

PHP_ARG_ENABLE(

   myfirst,

   [Whether to enable the "myfirst" extension],

   [enable-myfirst    Enable"myfirst" extension support])

if test $PHP_Myfirst !="no"; then

   PHP_SUBST(Myfirst_SHARED_LIBADD)

   PHP_NEW_EXTENSION(myfirst, myfirst.c, $ext_shared)

fi

上面PHP_ARG_ENABLE函数有三个参数,第一个参数是我们的扩展名(注意不用加引号),第二个参数是当我们运行./configure脚本时显示的内容,最后一个参数则是我们在调用./configure--help时显示的帮助信息。PHP_SUBST函数只是php官方对autoconf中AC_SUBST函数的一层封装。PHP_NEW_EXTENSION函数声明了这个扩展的名称、需要的源文件名、扩展的编译形式。如果扩展使用了多个文件,可以将文件名罗列在函数的参数里,如:PHP_NEW_EXTENSION(sample, sample.c sample2.c sample3.c, $ext_shared)最后的$ext_shared参数用来声明这个扩展为动态库,在php运行时动态加载的。

2.源文件

在完成了配置文件后,下面的就是完成扩展主逻辑的头文件和C文件。

头文件

//php_myfirst.h

#ifndef Myfirst_H

#define Myfirst_H

//加载config.h,如果配置了的话

#ifdef HAVE_CONFIG_H

#include "config.h"

#endif

//加载php头文件

#include "php.h"

#define phpext_myfirst_ptr &myfirst_module_entry

extern zend_module_entrymyfirst_module_entry;

#endif

    C文件

//myfirst.c

#include "php_myfirst.h"

//module entry

zend_module_entrymyfirst_module_entry = {

#if ZEND_MODULE_API_NO >= 20010901

     STANDARD_MODULE_HEADER,

#endif

    "myfirst",//扩展名称

    NULL, /*Functions */

    NULL, /*MINIT */

    NULL, /*MSHUTDOWN */

    NULL, /*RINIT */

    NULL, /*RSHUTDOWN */

    NULL, /*MINFO */

#if ZEND_MODULE_API_NO >= 20010901

    "2.1",//扩展的版本

#endif

    STANDARD_MODULE_PROPERTIES

};

#ifdef COMPILE_DL_Myfirst

ZEND_GET_MODULE(myfirst)

#endif

3.扩展编译

准备好了扩展需要编译的源文件,接下来需要的便是把它们编译成目标文件了。

第一步:根据config.m4文件使用phpize生成一个configure脚本、Makefile等文件:

$ phpize

PHP Api Version: 20041225

Zend Module Api No: 20050617

Zend Extension Api No: 220050617

现在查看扩展所在的目录,会发现phpize程序根据config.m4里的信息生成了许多编译php扩展必须的文件,比如makefiles等。

第二部:运行./configure脚本,然后执行make; make test即可。如果没有错误,那么在module文件夹下面便会生成扩展的目标文件 myfirst.so,这里由于之前我们在配置文件里写申明的是动态扩展,所以会被编译成动态库。

现在,先让我们执行一下PHP源码根目录下的./buildconf —force,再执行./configure --help命令。会发现myfirst扩展的信息已经出现了。

为了使PHP能够找到需要的扩展文件,我们需要把编译好的so文件复制到PHP的扩展目录下,并在php.ini中配置:

extension_dir=/usr/local/lib/php/modules/

extension=myfirst.so

这样php就会在每次启动的时候自动加载我们的扩展了。

4.扩展功能函数编写

前面我们已经生成好了一份扩展框架,但它是没有什么实际作用的,我们还需要编写具体的功能函数。

#definePHP_FUNCTION         ZEND_FUNCTION

#defineZEND_FUNCTION(name)    ZEND_NAMED_FUNCTION(ZEND_FN(name))

#defineZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)

#define ZEND_FN(name)                zif_##name

其中zif是zend internal function的意思,zif前缀是可供PHP语言调用的函数在C语言中的函数名称前缀。

ZEND_FUNCTION(myfirst_hello)

{

    php_printf("HelloWorld!\n");

}

上面的函数在C语言中宏展开后是这样的:

voidzif_myfirst_hello(INTERNAL_FUNCTION_PARAMETERS)

{

    php_printf("HelloWorld!\n");

}

函数的功能已经实现了,但是还不能在程序中调用,因为这个函数还没有在扩展模块中注册。现在看下扩展中zend_module_entry

myfirst_module_entry(它是联系C扩展与PHP语言的重要纽带)中/*Functions*/的值为NULL,这是之前还没有编写函数。现在我们可以将编写的函数赋值给它了,这个值需要是zend_function_entry[]类型:

static zend_function_entrymyfirst_functions[] = {

     ZEND_FE(myfirst_hello, NULL)

    { NULL, NULL,NULL }

};

其中最后的{NULL,NULL,NULL}是固定不变的。ZEND_FE()宏函数是对myfirst_hello函数的一个声明,如果有多个函数,可以直接以类似的形式添加到{NULL,NULL,NULL}之前,注意每个之间不需要加逗号。确保一切无误后,我们替换掉zend_module_entry里的原有成员,现在应该是这样的:

ZEND_FUNCTION(myfirst_hello)

{

    php_printf("HelloWorld!\n");

}

static zend_function_entrymyfirst_functions[] = {

    ZEND_FE(myfirst_hello,       NULL)

    { NULL, NULL,NULL }

};

zend_module_entrymyfirst_module_entry = {

#if ZEND_MODULE_API_NO >= 20010901

     STANDARD_MODULE_HEADER,

#endif

    "myfirst",//扩展名称。

    myfirst_functions,/* Functions */

    NULL, /*MINIT */

    NULL, /*MSHUTDOWN */

    NULL, /*RINIT */

    NULL, /*RSHUTDOWN */

    NULL, /*MINFO */

#if ZEND_MODULE_API_NO >= 20010901

    "2.1",//这个地方是我们扩展的版本

#endif

    STANDARD_MODULE_PROPERTIES

};

这样我们就完成扩展的一个简单功能,然后再重新configure、make、make test,并复制.so文件到extension dir目录。

最后写一个脚本在命令行测试,应该可以输出helloworld了。

hp

myfirst_hello();

?>


-------------------------------------------------------------------------------------

黑夜路人,一个关注开源技术、乐于学习、喜欢分享的程序员


博客:http://blog.csdn.net/heiyeshuwu

微博:http://weibo.com/heiyeluren

微信:heiyeluren2012  

想获取更多IT开源技术相关信息,欢迎关注微信!

微信二维码扫描快速关注本号码:


?




作者:heiyeshuwu 发表于2014-10-13 11:04:24 原文链接

阅读:904 评论:2 查看评论

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

CakePHP 프로젝트 구성 CakePHP 프로젝트 구성 Sep 10, 2024 pm 05:25 PM

이번 장에서는 CakePHP의 환경 변수, 일반 구성, 데이터베이스 구성, 이메일 구성에 대해 알아봅니다.

Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Dec 24, 2024 pm 04:42 PM

PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

CakePHP 날짜 및 시간 CakePHP 날짜 및 시간 Sep 10, 2024 pm 05:27 PM

cakephp4에서 날짜와 시간을 다루기 위해 사용 가능한 FrozenTime 클래스를 활용하겠습니다.

CakePHP 파일 업로드 CakePHP 파일 업로드 Sep 10, 2024 pm 05:27 PM

파일 업로드 작업을 위해 양식 도우미를 사용할 것입니다. 다음은 파일 업로드의 예입니다.

CakePHP 라우팅 CakePHP 라우팅 Sep 10, 2024 pm 05:25 PM

이번 장에서는 라우팅과 관련된 다음과 같은 주제를 학습하겠습니다.

CakePHP 토론 CakePHP 토론 Sep 10, 2024 pm 05:28 PM

CakePHP는 PHP용 오픈 소스 프레임워크입니다. 이는 애플리케이션을 훨씬 쉽게 개발, 배포 및 유지 관리할 수 있도록 하기 위한 것입니다. CakePHP는 강력하고 이해하기 쉬운 MVC와 유사한 아키텍처를 기반으로 합니다. 모델, 뷰 및 컨트롤러 gu

PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 Dec 20, 2024 am 11:31 AM

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

CakePHP 유효성 검사기 만들기 CakePHP 유효성 검사기 만들기 Sep 10, 2024 pm 05:26 PM

컨트롤러에 다음 두 줄을 추가하면 유효성 검사기를 만들 수 있습니다.

See all articles