日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > php >内容正文

php

php extname shared,PHP: 编写第一个PHP扩展

發(fā)布時(shí)間:2024/6/1 php 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php extname shared,PHP: 编写第一个PHP扩展 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

今天看了一些PHP擴(kuò)展的入門文章,很好的文章,但看的還是很吃力。主要是因?yàn)椴涣私馕恼吕镎f(shuō)的生命周期,內(nèi)存分配,SAPI這些概念。然后代碼里全是宏,如果不查源碼,和看天書(shū)沒(méi)什么區(qū)別。所以想記錄一下從源碼的角度分析 hello.c 這個(gè)文件的過(guò)程,其它文章里有的我就不重復(fù)了,我先放代碼,這里有一個(gè)部分和原文章不一樣。

隨便新建一個(gè)文件夾,里面包含下面3個(gè)文件:

config.m4

PHP_ARG_ENABLE(hello, whether to enable Hello

World support,

[ --enable-hello Enable Hello World support])

if test "$PHP_HELLO" = "yes"; then

AC_DEFINE(HAVE_HELLO, 1, [Whether you have Hello World])

PHP_NEW_EXTENSION(hello, hello.c, $ext_shared)

fi

php_hello.h

#ifndef PHP_HELLO_H

#define PHP_HELLO_H 1

#define PHP_HELLO_WORLD_VERSION "1.0"

#define PHP_HELLO_WORLD_EXTNAME "hello"

PHP_FUNCTION(hello_world);

extern zend_module_entry hello_module_entry;

#define phpext_hello_ptr &hello_module_entry

#endif

hello.c

#ifdef HAVE_CONFIG_H

#include "config.h"

#endif

#include "php.h"

#include "php_hello.h"

// 模塊所包含的函數(shù)列表信息

static zend_function_entry hello_functions[] = {

PHP_FE(hello_world, NULL)

{NULL, NULL, NULL}

};

// 模塊自身的相關(guān)信息

// 如模塊名,模塊包含的函數(shù),生命周期,版本號(hào)等

zend_module_entry hello_module_entry = {

#if ZEND_MODULE_API_NO >= 20010901

STANDARD_MODULE_HEADER,

#endif

PHP_HELLO_WORLD_EXTNAME,

hello_functions,

NULL,

NULL,

NULL,

NULL,

NULL,

#if ZEND_MODULE_API_NO >= 20010901

PHP_HELLO_WORLD_VERSION,

#endif

STANDARD_MODULE_PROPERTIES

};

// 與動(dòng)態(tài)加載有關(guān) Dynamic Loading,后面解釋

#ifdef COMPILE_DL_HELLO

ZEND_GET_MODULE(hello)

#endif

// 你的擴(kuò)展函數(shù)

PHP_FUNCTION(hello_world)

{

RETURN_STRING("Hello World", 1);

}

運(yùn)行下面的命令可以驗(yàn)證擴(kuò)展。

phpize

./configure

make

php -dextension=modules/hello.so -r "echo hello_world();"

和原文不同的是這里使用 zend_function_entry 而不是 function_entry。這個(gè)和 PHP 的版本有關(guān),不然編譯會(huì)出錯(cuò)。

我們先看這一段代碼

static zend_function_entry hello_functions[] = {

PHP_FE(hello_world, NULL)

{NULL, NULL, NULL}

};

如果你查看 PHP 官方文檔,也有可能會(huì)這樣寫。

static zend_function_entry hello_functions[] = {

PHP_FE(hello_world, NULL)

ZEND_FE_END

};

其實(shí)說(shuō)到底,把這些你看不懂的宏的定義找出來(lái),就好了,我們就先找 zend_function_entry,因?yàn)槲业脑创a在下面這個(gè)路徑下,所以我先 cd 過(guò)去。

/usr/local/Cellar/php56/5.6.32_8/include/php

然后用下面的命令找 zend_function_entry 的定義。

grep -rnw . -e 'zend_function_entry'

發(fā)現(xiàn)在 zend_API.h 這個(gè)文件。

./Zend/zend_API.h:41:} zend_function_entry;

源碼是一個(gè)結(jié)構(gòu)體,用到存儲(chǔ)函數(shù)的信息。

typedef struct _zend_function_entry {

const char *fname;

void (*handler)(INTERNAL_FUNCTION_PARAMETERS);

const struct _zend_arg_info *arg_info;

zend_uint num_args;

zend_uint flags;

} zend_function_entry;

接著再看 PHP_FE,同理使用下面命令。

grep -rnw . -e 'PHP_FE'

得到下面的結(jié)果。

./main/php.h:352:#define PHP_FE ZEND_FE

再找 ZEND_FE,下面就不寫了,最后查到是這個(gè)定義。

#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeo

f(struct _zend_arg_info)-1), flags },

#define ZEND_FE(name, arg_info) ZEND_FENTRY(name, ZEND_FN(name), arg_info, 0)

其實(shí)就是一個(gè)關(guān)于函數(shù)結(jié)構(gòu)體的信息,和之前的 zend_function_entry 對(duì)應(yīng)。

再看 zend_module_entry 這一段代碼,其實(shí)做法也是參照上面的,#if ZEND_MODULE_API_NO >= 20010901 是用來(lái)判斷 api 版本是否大于等于 20010901 (這個(gè)是年月日),如果大于則在編譯期包含 STANDARD_MODULE_HEADER 這個(gè)宏,這些信息都可以在下面這個(gè)源文件找到,ZEND_MODULE_API_NO 這個(gè)宏也是定義這個(gè)文件中的。

zend_modules.h

最后說(shuō)說(shuō)這個(gè)

// 與動(dòng)態(tài)加載有關(guān) Dynamic Loading,后面解釋

#ifdef COMPILE_DL_HELLO

ZEND_GET_MODULE(hello)

#endif

其實(shí)我也不是很懂,查了 ZEND_GET_MODULE 這個(gè)宏,他是一個(gè)函數(shù),用于在運(yùn)行時(shí)供 Zend 引擎獲取模塊的名字。今天大概就到這里,下次再寫函數(shù)帶數(shù)的情況。

總結(jié)

以上是生活随笔為你收集整理的php extname shared,PHP: 编写第一个PHP扩展的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。