php 扩展之 – 获取函数参数

前面的一篇文章, 我们知道了怎么创建一个函数, 下面来瞅瞅是怎么获得这个函数的参数的。

来看看php原型

function hello($name) {
  echo "hello " + $name;
}

test.php

 hello('Greed');
PHP_FUNCTION(hello)
{
	char *name;
	int name_len;
	
	/* 获取参数
	   ZEND_NUM_ARGS()  告诉zend engine 要去参数
	   TSRMLS_CC 保障线程安全, 检查返回值是不是 SUCCESS or FAILURE
	   "s"  表示要取得char 类型的参数
	   $name , $name_len  把参数取出放到这里
	   取参数是可变的, 根据参数的个数设定, 如, 表示取三个参数, 第三个是可选的
	   zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z", &name, &rxt, &source) 
	   */
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
	    RETURN_NULL();
	}
	
	php_printf("Hello %s ", name);
	
	RETURN_TRUE;
}

是不是简单的。 哦, 什么,对获取参数不是很明白, 好吧, 再来看个例子吧。

看看原型

function hello_add($a, $b, $return_long = false) {

    $sum = (int)$a + (float)$b;

    if ($return_long) {
        return intval($sum);
    } else {
        return floatval($sum);
    }
}

test.php

echo hello_add(12.2, 1.3); 
 echo "\n";
echo hello_add(12.2, 1.3, true);
PHP_FUNCTION(hello_add)
{
    long a;
    double b;
    zend_bool return_long = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|b", &a, &b, &return_long) == FAILURE) {
        RETURN_NULL();
    }

    if (return_long) {
        RETURN_LONG(a + b);
    } else {
        RETURN_DOUBLE(a + b);
    }
}

下表说明了字母和类型是怎么对应的了
表: zend_parse_parameters() 字母对应的类型

类型 字母 变量类型
Boolean b zend_bool
Long l long
Double d double
String s char *, int
Resource r zval *
Array a zval *
Object o zval*
zval z zval*

上面可以看到有变量是 zval , 这个是php 的复杂类型。 这个在下来介绍。

评论

php 扩展 – 模块全局变量和定义函数

在写扩展的时候, 经常会用到一个模块公用的变量, 这就是模块的全局变量。 直接上代码吧, 很明显的,就是, 申明 -> 初始化 -> 使用 -> 析构
在这里也加上一个怎么定义一个函数, 以供外部使用,定义函数也是最常用的

这只是全部代码的一部分, 完整的代码请参考我的helloworld

test.php

echo my_id();

phpext.h

/**
 * 模块 全局变量 变量
 */
ZEND_BEGIN_MODULE_GLOBALS(phpext)
 long id;
ZEND_END_MODULE_GLOBALS(phpext)

// 模块内获取全局变量
#ifdef ZTS
#define PHPEXT_G(v) TSRMG(phpext_globals_id, zend_phpext_globals *, v)
#else
#define PHPEXT_G(v) (phpext_globals.v)
#endif

// 声明全局变量初始化函数
static void php_phpext_init_globals(zend_phpext_globals *phpext_globals TSRMLS_DC);
// 析构全局变量
static void php_phpext_shutdown_globals(zend_phpext_globals *phpext_globals TSRMLS_DC);

ZEND_FUNCTION(my_id);

phpext.c

// 定义模块函数
zend_function_entry phpext_functions[]	=	{
	ZEND_FE(helloworld, NULL)
	ZEND_FE(my_id, NULL)
	{NULL, NULL, NULL}
};


ZEND_FUNCTION(my_id) {
       // 使用 全局变量 id
	PHPEXT_G(id)++;

	RETURN_LONG(PHPEXT_G(id));
}

// 全局变量初始化函数
static void php_phpext_init_globals(zend_phpext_globals *phpext_globals TSRMLS_DC) {
}
static void php_phpext_shutdown_globals(zend_phpext_globals *phpext_globals TSRMLS_DC) {
}

ZEND_MINIT_FUNCTION(phpext) {
         // 初始化
	ZEND_INIT_MODULE_GLOBALS(phpext, php_phpext_init_globals, php_phpext_shutdown_globals);
	return SUCCESS;
}
ZEND_RINIT_FUNCTION(phpext) {
	// 初始化为0
        PHPEXT_G(id) = 0;
	return SUCCESS;
}

评论 Trackback / Pingback (1)

php 扩展之 – helloworld

玩了php开发有段时间了,得感谢抚琴居(可惜访问不到了), 风雪之隅, 特别感谢benxi 的指导(本来写c 就少, 让我理解了一些基本概念)。

准备写一些php 扩展开发相关的文章, 让知识延续吧。

先来个helloworld 吧。
代码应该不难理解, 简单说一下:
包含进了php 的基本头文件和开发扩展要到的头文件, 申明了模块的入口zend_module_entry phpext_module_entry,定义了模块的函数zend_function_entry phpext_functions

在几个模块相关的函数
ZEND_MINIT_FUNCTION(phpext); 模块初始化
ZEND_MSHUTDOWN_FUNCTION(phpext); 模块结束处理
ZEND_RINIT_FUNCTION(phpext); 请求初始化
ZEND_RSHUTDOWN_FUNCTION(phpext); 请求结束

顺序是 MINT -> RINIT -> RSHUTDOWN -> MSHUTDOWN

在这里我申明了一个常量
REGISTER_STRING_CONSTANT(“CONST_HELLOWORLD”, “helloworld”, CONST_CS | CONST_PERSISTENT);

安装: make && make install 剩下的你懂的,

test.php


helloworld();
echo CONST_HELLOWORLD;

phpext.h

#ifndef PHP_PHPEXT_H
#define PHP_PHPEXT_H

#define PHPEXT_VERSION		"0.8"
#define PHPEXT_MICRO_IN_SEC	1000000.00

#include "php.h"
#include "main/php_version.h"
#include "main/php_config.h"
#include "zend.h"
#include "zend_API.h"
#include "zend_hash.h"
#include "zend_constants.h"
#include "TSRM.h"

extern zend_module_entry phpext_module_entry;
#define phpext_phpext_ptr &phpext_module_entry

/**
 * 模块 global 变量
 */
ZEND_BEGIN_MODULE_GLOBALS(phpext)
ZEND_END_MODULE_GLOBALS(phpext)

#ifdef ZTS
#define PHPEXT_G(v) TSRMG(phpext_globals_id, zend_phpext_globals *, v)
#else
#define PHPEXT_G(v) (phpext_globals.v)
#endif

//获取 执行时间信息
double phpext_get_utime(void);

static void php_phpext_init_globals(zend_phpext_globals *phpext_globals TSRMLS_DC);
static void php_phpext_shutdown_globals(zend_phpext_globals *phpext_globals TSRMLS_DC);

ZEND_MINIT_FUNCTION(phpext);
ZEND_MSHUTDOWN_FUNCTION(phpext);
ZEND_RINIT_FUNCTION(phpext);
ZEND_RSHUTDOWN_FUNCTION(phpext);
ZEND_MINFO_FUNCTION(phpext);

#ifdef ZEND_ENGINE_2
	ZEND_MODULE_POST_ZEND_DEACTIVATE_D(phpext);
#endif

ZEND_FUNCTION(helloworld);

#endif

phpext.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include 

#include "php.h"
#include "zend.h"
#include "TSRM.h"
#include "zend_alloc.h"
#include "zend_ini.h"
#include "zend_API.h"

#include "ext/standard/info.h"

#include "phpext.h"


ZEND_DECLARE_MODULE_GLOBALS(phpext)

ZEND_GET_MODULE(phpext)

// 定义模块函数
zend_function_entry phpext_functions[]	=	{
	ZEND_FE(helloworld, NULL)
	{NULL, NULL, NULL}
};

// 定义模块入口
zend_module_entry phpext_module_entry = {
	STANDARD_MODULE_HEADER,
	"phpext",
	phpext_functions,
	ZEND_MINIT(phpext),
	ZEND_MSHUTDOWN(phpext),
	ZEND_RINIT(phpext),
#ifdef ZEND_ENGINE_2
	ZEND_RSHUTDOWN(phpext),
#else
	NULL,
#endif
	ZEND_MINFO(phpext),
	PHPEXT_VERSION,
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION >= 6
	NO_MODULE_GLOBALS,
#endif
#ifdef ZEND_ENGINE_2
	ZEND_MODULE_POST_ZEND_DEACTIVATE_N(phpext),
#else
	NULL,
#endif
	STANDARD_MODULE_PROPERTIES_EX
};


/**
 * 注册函数
 */
ZEND_FUNCTION(helloworld) {
	php_printf("helloworld");

	RETURN_TRUE;
}

ZEND_INI_BEGIN()
ZEND_INI_END()

static void php_phpext_init_globals(zend_phpext_globals *phpext_globals TSRMLS_DC) {
}

static void php_phpext_shutdown_globals(zend_phpext_globals *phpext_globals TSRMLS_DC) {
}

/**
 * 模块初始化,  Module Initialization,apache 启动的时候初始化模块,适合于初始模块的全局变量,常量
 */
ZEND_MINIT_FUNCTION(phpext) {
        //定义常量 CONST_HELLOWORLD
	REGISTER_STRING_CONSTANT("CONST_HELLOWORLD", "helloworld", CONST_CS | CONST_PERSISTENT);

	ZEND_INIT_MODULE_GLOBALS(phpext, php_phpext_init_globals, php_phpext_shutdown_globals);
	REGISTER_INI_ENTRIES();

	return SUCCESS;
}

/**
 * 模块结束处理, Module Shutdown, apache 关闭或者一个cli  SAPIs 执行结束
 */
ZEND_MSHUTDOWN_FUNCTION(phpext) {
	UNREGISTER_INI_ENTRIES();

#ifdef ZTS
	ts_free_id(phpext_globals_id);
#else
	php_phpext_shutdown_globals(&phpext_globals TSRMLS_CC);
#endif

	return SUCCESS;
}

/**
 * 请求初始化  , Request Initialization, 一个新的cgi 请求的时候调用
 */
ZEND_RINIT_FUNCTION(phpext) {

	return SUCCESS;
}

/**
 * 请求结束, Request Shutdown
 */
ZEND_RSHUTDOWN_FUNCTION(phpext) {
	return SUCCESS;
}


/**
 * 在php info 里打印的模块信息
 */
ZEND_MINFO_FUNCTION(phpext) {
	php_info_print_table_start();
	php_info_print_table_row(2, "version", PHPEXT_VERSION);
	php_info_print_table_end();
}

ZEND_MODULE_POST_ZEND_DEACTIVATE_D(phpext) {

	return SUCCESS;
}

makefile

PHP_DIR   = /usr/local/php
PHP_INC   = $(PHP_DIR)/include/php
PHP_EXT   = /usr/local/php/extensions
VPATH     =

PROFILE_FOG_VER = 0.2.6
LIBC_VER  = $(shell ls /lib/libc-*.so | cut -c11-13)
GCC_VER   = $(shell gcc -v 2>&1 | grep "gcc version" | cut --characters="13 15 17")

TAR_OBJ   = phpext.o
TAR_SYM   = phpext.so
TAR_EXT   = $(TAR_SYM).$(PROFILE_FOG_VER).libc.$(LIBC_VER)
INC_SYS   = -I/usr/include
LNK_SYS   = -L/usr/lib64 -rdynamic
#LNK_SYS   = -L/usr/lib -rdynamic #32 bit arch


INC_PHP   = -I$(PHP_INC) -I$(PHP_INC)/main -I$(PHP_INC)/TSRM -I$(PHP_INC)/Zend
LNK_PHP   =


INC = $(INC_PHP) $(INC_SYS)
LIB = $(LNK_SYS)


CC    = gcc
CFLAG = -g -fpic -DCOMPILE_DL=1  -Wall 
LFLAG = -g -shared -m64
#LFLAG = -shared #32 bit arch

all: $(TAR_EXT)
$(TAR_EXT): $(TAR_OBJ)
ifneq ($(PHP_DIR),)
	$(CC) $(LFLAG) -o $(TAR_EXT) $(TAR_OBJ) $(INC) $(LIB)
	@echo $@
else
	@echo -e "\n Canceled. \n"
endif

static: $(TAR_OBJ)
	$(CC) $(LFLAG)  -static -o $(TAR_EXT) $(TAR_OBJ) $(INC) $(LIB)
	@echo $@

%.o: %.c %.h
ifneq ($(PHP_DIR),)
	$(CC) $(CFLAG) -c $*.c $(INC)
	@echo $@
else
	@echo -e "\n Canceled. \n"
endif

clean: 
	rm -f *.o
	rm -f *.so*
	rm -f $(PHP_EXT)/$(TAR_SYM).*

install:
	cp $(TAR_EXT) $(PHP_EXT)/$(TAR_EXT)
	@echo
	@echo Module has been installed to: $(PHP_EXT)/$(TAR_SYM)
	@echo

uninstall:
	rm -f $(PHP_EXT)/(TAR_SYM).*

评论 Trackback / Pingback (1)