4 Commits

Author SHA1 Message Date
Xinchen Hui
6a2bf0e8af Update README 2015-10-26 21:11:12 -07:00
Xinchen Hui
aaf49be301 trigger triavis 2015-10-26 21:05:41 -07:00
Xinchen Hui
d3323aa9fe enable travis 2015-10-26 20:54:55 -07:00
Xinchen Hui
50d32564d2 Master is only for PHP5.X now 2015-02-25 22:23:05 +08:00
13 changed files with 409 additions and 373 deletions

View File

@@ -1,21 +1,26 @@
language: php language: php
addons:
apt:
packages:
- liblua5.2-dev
php: php:
- 5.6
- 5.5
- 5.4
- 5.3 - 5.3
- 5.3.3 - 5.4
- 5.5
- 5.6
before_install: notifications:
- sudo apt-get update -qq email: false
- sudo apt-get install -y libjson0-dev libjson0 php5-cli php5-dev liblua5.2-dev irc: "irc.efnet.org#php.yaf"
env:
- REPORT_EXIT_STATUS=1 NO_INTERACTION=1
#Compile
before_script: before_script:
# Compile PHP
- ./travis/compile.sh - ./travis/compile.sh
script: # Run PHPs run-tests.php
- ./travis/build_check.sh script: make test

View File

@@ -2,4 +2,3 @@ lua
Johannes Schlueter Johannes Schlueter
Marcelo Araujo Marcelo Araujo
Xinchen Hui Xinchen Hui
Helmut Januschka

View File

@@ -1,2 +1,6 @@
"Lua is a powerful, fast, light-weight, embeddable scripting language." ##PHP Lua
[![Build Status](https://secure.travis-ci.org/laruence/php-lua.png)](https://travis-ci.org/laruence/php-lua)
This extension embeds the lua interpreter and offers an OO-API to lua variables and functions. This extension embeds the lua interpreter and offers an OO-API to lua variables and functions.
"Lua is a powerful, fast, light-weight, embeddable scripting language."

View File

@@ -1,6 +1,7 @@
dnl $Id: config.m4 321796 2012-01-05 17:23:48Z laruence $ dnl $Id: config.m4 321796 2012-01-05 17:23:48Z laruence $
PHP_ARG_WITH(lua, for lua support, PHP_ARG_WITH(lua, for lua support,
[ --with-lua=[DIR] Include php lua support]) [ --with-lua=[DIR] Include php lua support])
PHP_ARG_WITH(lua-version, to specify a custom lua version, [ --with-lua-version=[VERSION]] Use the specified lua version.) PHP_ARG_WITH(lua-version, to specify a custom lua version, [ --with-lua-version=[VERSION]] Use the specified lua version.)
if test "$PHP_LUA" != "no"; then if test "$PHP_LUA" != "no"; then

515
lua.c Executable file → Normal file
View File

@@ -13,9 +13,9 @@
| Author : Johannes Schlueter <johannes@php.net> | | Author : Johannes Schlueter <johannes@php.net> |
| Xinchen Hui <laruence@php.net> | | Xinchen Hui <laruence@php.net> |
| Marcelo Araujo <msaraujo@php.net> | | Marcelo Araujo <msaraujo@php.net> |
| Helmut Januschka <helmut@januschka.com> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
*/ $Id: lua.c 324348 2012-03-19 03:12:15Z laruence $
*/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
@@ -90,6 +90,7 @@ ZEND_GET_MODULE(lua)
/** {{{ static void php_lua_stack_dump(lua_State* L) /** {{{ static void php_lua_stack_dump(lua_State* L)
* just for debug * just for debug
*/ */
#ifdef PHP_LUA_DEBUG
static void php_lua_stack_dump(lua_State* L) { static void php_lua_stack_dump(lua_State* L) {
int i = 1; int i = 1;
int n = lua_gettop(L); int n = lua_gettop(L);
@@ -120,12 +121,14 @@ static void php_lua_stack_dump(lua_State* L) {
printf("\n"); printf("\n");
} }
} }
#endif
/* }}} */ /* }}} */
/** {{{ static int php_lua_atpanic(lua_State *L) /** {{{ static int php_lua_atpanic(lua_State *L)
*/ */
static int php_lua_atpanic(lua_State *L) { static int php_lua_atpanic(lua_State *L) {
php_error_docref(NULL, E_ERROR, "lua panic (%s)", lua_tostring(L, 1)); TSRMLS_FETCH();
php_error_docref(NULL TSRMLS_CC, E_ERROR, "lua panic (%s)", lua_tostring(L, 1));
lua_pop(L, 1); lua_pop(L, 1);
zend_bailout(); zend_bailout();
return 0; return 0;
@@ -135,14 +138,13 @@ static int php_lua_atpanic(lua_State *L) {
/** {{{ static int php_lua_print(lua_State *L) /** {{{ static int php_lua_print(lua_State *L)
*/ */
static int php_lua_print(lua_State *L) { static int php_lua_print(lua_State *L) {
zval rv;
int i = 0; int i = 0;
int nargs = lua_gettop(L);
for (i = 1; i <= nargs; ++i) { TSRMLS_FETCH();
php_lua_get_zval_from_lua(L, i, NULL, &rv); for (i = -lua_gettop(L) ; i<0; i++) {
zend_print_zval_r(&rv, 1); zval *tmp = php_lua_get_zval_from_lua(L, i, NULL TSRMLS_CC);
zval_ptr_dtor(&rv); zend_print_zval_r(tmp, 1 TSRMLS_CC);
zval_ptr_dtor(&tmp);
} }
return 0; return 0;
} }
@@ -170,102 +172,146 @@ static void * php_lua_alloc_function(void *ud, void *ptr, size_t osize, size_t n
} }
/* }}} */ /* }}} */
static void php_lua_dtor_object(zend_object *object) /* {{{ */ { /** {{{ static void php_lua_dtor_object(void *object, zend_object_handle handle TSRMLS_DC)
php_lua_object *lua_obj = php_lua_obj_from_obj(object); * the dtor function for lua object
*/
static void php_lua_dtor_object(void *object, zend_object_handle handle TSRMLS_DC) {
php_lua_object *lua_obj = (php_lua_object *)object;
zend_object_std_dtor(&(lua_obj->obj)); zend_object_std_dtor(&(lua_obj->obj) TSRMLS_CC);
if (lua_obj->L) { if (lua_obj->L) {
lua_close(lua_obj->L); lua_close(lua_obj->L);
} }
efree(lua_obj);
} }
/* }}} */ /* }}} */
/** {{{ static zend_object_value php_lua_create_object(zend_class_entry *ce) /** {{{ static zend_object_value php_lua_create_object(zend_class_entry *ce TSRMLS_DC)
*
* the create object handler for lua
*/ */
zend_object *php_lua_create_object(zend_class_entry *ce) static zend_object_value php_lua_create_object(zend_class_entry *ce TSRMLS_DC) {
{ zend_object_value obj = {0};
php_lua_object* intern; php_lua_object *lua_obj = NULL;
lua_State *L; lua_State *L = NULL;
L = luaL_newstate(); L = lua_newstate(php_lua_alloc_function, NULL);
lua_atpanic(L, php_lua_atpanic); lua_atpanic(L, php_lua_atpanic);
intern = emalloc(sizeof(php_lua_object) + sizeof(zval) * (ce->default_properties_count - 1)); lua_obj = emalloc(sizeof(php_lua_object));
if (!intern) { if (!lua_obj) {
php_error_docref(NULL, E_ERROR, "alloc memory for lua object failed"); php_error_docref(NULL TSRMLS_CC, E_ERROR, "alloc memory for lua object failed");
} }
intern->L = L; lua_obj->L = L;
zend_object_std_init(&(lua_obj->obj), ce TSRMLS_CC);
zend_object_std_init(&intern->obj, ce); #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4)
object_properties_init(&intern->obj, ce); zend_hash_copy(lua_obj->obj.properties, &ce->default_properties,
#if (PHP_MINOR_VERSION < 4)
(copy_ctor_func_t) zval_add_ref,
#else
zval_copy_property_ctor(ce),
#endif
(void *)0, sizeof(zval *));
#elif (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION > 3)
object_properties_init(&(lua_obj->obj), ce);
#endif
intern->obj.handlers = &lua_object_handlers; obj.handle = zend_objects_store_put(lua_obj, php_lua_dtor_object, NULL, NULL TSRMLS_CC);
obj.handlers = &lua_object_handlers;
return &intern->obj;
return obj;
} }
/* }}} */ /* }}} */
/** {{{ static zval * php_lua_read_property(zval *object, zval *member, int type) /** {{{ static zval * php_lua_read_property(zval *object, zval *member, int type TSRMLS_DC)
*/ */
zval *php_lua_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv){ #if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4)) || (PHP_MAJOR_VERSION < 5)
lua_State *L = NULL; static zval * php_lua_read_property(zval *object, zval *member, int type TSRMLS_DC) {
#else
static zval * php_lua_read_property(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC) {
#endif
zval *retval = NULL;
lua_State *L = NULL;
zval *tmp_member = NULL; zval *tmp_member = NULL;
#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION > 3))
(void)key;
#endif
if (type != BP_VAR_R) { if (type != BP_VAR_R) {
ZVAL_NULL(rv); MAKE_STD_ZVAL(retval);
return rv; ZVAL_NULL(retval);
return retval;
} }
if (Z_TYPE_P(member) != IS_STRING) { if (Z_TYPE_P(member) != IS_STRING) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member; *tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member); zval_copy_ctor(tmp_member);
convert_to_string(tmp_member); convert_to_string(tmp_member);
member = tmp_member; member = tmp_member;
} }
L = (Z_LUAVAL_P(object))->L; L = Z_LUAVAL_P(object);
#if (LUA_VERSION_NUM < 502) #if (LUA_VERSION_NUM < 502)
lua_getfield(L, LUA_GLOBALSINDEX, Z_STRVAL_P(member)); lua_getfield(L, LUA_GLOBALSINDEX, Z_STRVAL_P(member));
#else #else
lua_getglobal(L, Z_STRVAL_P(member)); lua_getglobal(L, Z_STRVAL_P(member));
#endif #endif
php_lua_get_zval_from_lua(L, -1, object, rv); retval = php_lua_get_zval_from_lua(L, -1, object TSRMLS_CC);
Z_DELREF_P(retval);
lua_pop(L, 1); lua_pop(L, 1);
return rv;
if (tmp_member) {
zval_ptr_dtor(&tmp_member);
}
return retval;
} }
/* }}} */ /* }}} */
/** {{{ static void php_lua_write_property(zval *object, zval *member, zval *value) /** {{{ static void php_lua_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
*/ */
static void php_lua_write_property(zval *object, zval *member, zval *value, void ** key) { #if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4)) || (PHP_MAJOR_VERSION < 5)
static void php_lua_write_property(zval *object, zval *member, zval *value TSRMLS_DC) {
#else
static void php_lua_write_property(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC) {
#endif
lua_State *L = NULL; lua_State *L = NULL;
zval *tmp_member = NULL; zval *tmp_member = NULL;
#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION > 3))
(void)key;
#endif
if (Z_TYPE_P(member) != IS_STRING) { if (Z_TYPE_P(member) != IS_STRING) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member; *tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member); zval_copy_ctor(tmp_member);
convert_to_string(tmp_member); convert_to_string(tmp_member);
member = tmp_member; member = tmp_member;
} }
L = (Z_LUAVAL_P(object))->L; L = Z_LUAVAL_P(object);
#if (LUA_VERSION_NUM < 502) #if (LUA_VERSION_NUM < 502)
php_lua_send_zval_to_lua(L, member); php_lua_send_zval_to_lua(L, member TSRMLS_CC);
php_lua_send_zval_to_lua(L, value); php_lua_send_zval_to_lua(L, value TSRMLS_CC);
lua_settable(L, LUA_GLOBALSINDEX); lua_settable(L, LUA_GLOBALSINDEX);
#else #else
php_lua_send_zval_to_lua(L, value); php_lua_send_zval_to_lua(L, value TSRMLS_CC);
lua_setglobal(L, Z_STRVAL_P(member)); lua_setglobal(L, Z_STRVAL_P(member));
#endif #endif
if (tmp_member) { if (tmp_member) {
zval_ptr_dtor(tmp_member); zval_ptr_dtor(&tmp_member);
} }
} }
/* }}} */ /* }}} */
@@ -274,57 +320,72 @@ static void php_lua_write_property(zval *object, zval *member, zval *value, void
*/ */
static int php_lua_call_callback(lua_State *L) { static int php_lua_call_callback(lua_State *L) {
int order = 0; int order = 0;
zval retval; zval *return_value = NULL;
zval *func = NULL; zval **func = NULL;
zval *callbacks = NULL; zval *callbacks = NULL;
TSRMLS_FETCH();
order = lua_tonumber(L, lua_upvalueindex(1)); order = lua_tonumber(L, lua_upvalueindex(1));
callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1); callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1 TSRMLS_CC);
if (ZVAL_IS_NULL(callbacks)) { if (ZVAL_IS_NULL(callbacks)) {
return 0; return 0;
} }
func = zend_hash_index_find(Z_ARRVAL_P(callbacks), order);
if (!zend_is_callable(func, 0, NULL)) { MAKE_STD_ZVAL(return_value);
if (zend_hash_index_find(Z_ARRVAL_P(callbacks), order, (void **)&func) == FAILURE) {
return 0;
}
if (!zend_is_callable(*func, 0, NULL TSRMLS_CC)) {
return 0; return 0;
} else { } else {
zval *params; zval **params = NULL;
int i = 0; int i = 0;
int arg_num = lua_gettop(L); int arg_num = lua_gettop(L);
params = safe_emalloc(sizeof(zval), arg_num, 0); params = ecalloc(arg_num, sizeof(zval));
for (i = 0; i < arg_num; i++) {
php_lua_get_zval_from_lua(L, -(arg_num - i), NULL, &params[i]); for (; i<arg_num; i++) {
params[i] = php_lua_get_zval_from_lua(L, -(arg_num-i), NULL TSRMLS_CC);
} }
call_user_function(EG(function_table), NULL, func, &retval, arg_num, params); call_user_function(EG(function_table), NULL, *func, return_value, arg_num, params TSRMLS_CC);
php_lua_send_zval_to_lua(L, &retval);
for (i = 0; i<arg_num; i++) { php_lua_send_zval_to_lua(L, return_value TSRMLS_CC);
for (i=0; i<arg_num; i++) {
zval_ptr_dtor(&params[i]); zval_ptr_dtor(&params[i]);
} }
efree(params); efree(params);
zval_ptr_dtor(&retval); zval_ptr_dtor(&return_value);
return 1; return 1;
} }
} }
/* }}} */ /* }}} */
zval *php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj, zval *rv) /* {{{ */ { /** {{{ zval * php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj TSRMLS_DC)
*/
zval * php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj TSRMLS_DC) {
zval *retval;
MAKE_STD_ZVAL(retval);
ZVAL_NULL(retval);
switch (lua_type(L, index)) { switch (lua_type(L, index)) {
case LUA_TNIL: case LUA_TNIL:
ZVAL_NULL(rv); ZVAL_NULL(retval);
break; break;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
ZVAL_BOOL(rv, lua_toboolean(L, index)); ZVAL_BOOL(retval, lua_toboolean(L, index));
break; break;
case LUA_TNUMBER: case LUA_TNUMBER:
ZVAL_DOUBLE(rv, lua_tonumber(L, index)); ZVAL_DOUBLE(retval, lua_tonumber(L, index));
break; break;
case LUA_TSTRING: case LUA_TSTRING:
{ {
@@ -332,33 +393,32 @@ zval *php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj, zval *rv
size_t len = 0; size_t len = 0;
val = (char *)lua_tolstring(L, index, &len); val = (char *)lua_tolstring(L, index, &len);
ZVAL_STRINGL(rv, val, len); ZVAL_STRINGL(retval, val, len, 1);
} }
break; break;
case LUA_TTABLE: case LUA_TTABLE:
array_init(rv); array_init(retval);
lua_pushnil(L); /* first key */ lua_pushnil(L); /* first key */
while (lua_next(L, index-1) != 0) { while (lua_next(L, index-1) != 0) {
zval key, val; zval *key = NULL;
zval *val = NULL;
/* uses 'key' (at index -2) and 'value' (at index -1) */ /* uses 'key' (at index -2) and 'value' (at index -1) */
if (!php_lua_get_zval_from_lua(L, -2, lua_obj, &key)) { key = php_lua_get_zval_from_lua(L, -2, lua_obj TSRMLS_CC);
break; val = php_lua_get_zval_from_lua(L, -1, lua_obj TSRMLS_CC);
}
if (!php_lua_get_zval_from_lua(L, -1, lua_obj, &val)) { if (!key || !val) {
zval_ptr_dtor(&key);
/* there is a warning already in php_lua_get_zval_from_lua */ /* there is a warning already in php_lua_get_zval_from_lua */
break; break;
} }
switch(Z_TYPE(key)) { switch(Z_TYPE_P(key)) {
case IS_DOUBLE: case IS_DOUBLE:
case IS_LONG: case IS_LONG:
add_index_zval(rv, Z_DVAL(key), &val); add_index_zval(retval, Z_DVAL_P(key), val);
break; break;
case IS_STRING: case IS_STRING:
add_assoc_zval(rv, Z_STRVAL(key), &val); add_assoc_zval(retval, Z_STRVAL_P(key), val);
zval_ptr_dtor(&key);
break; break;
case IS_ARRAY: case IS_ARRAY:
case IS_OBJECT: case IS_OBJECT:
@@ -366,23 +426,22 @@ zval *php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj, zval *rv
break; break;
} }
lua_pop(L, 1); lua_pop(L, 1);
zval_ptr_dtor(&key);
} }
break; break;
case LUA_TFUNCTION: case LUA_TFUNCTION:
{ {
long ref_id = 0; long ref_id = 0;
if (!lua_obj) { if (!lua_obj) {
php_error_docref(NULL, E_WARNING, "corrupted Lua object"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "corrupted Lua object");
break; break;
} }
lua_pushvalue(L, index); lua_pushvalue(L, index);
ref_id = luaL_ref(L, LUA_REGISTRYINDEX); ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (!php_lua_closure_instance(rv, ref_id, lua_obj)) { if (!php_lua_closure_instance(retval, ref_id, lua_obj TSRMLS_CC)) {
php_error_docref(NULL, E_WARNING, "failed to initialize closure object"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize closure object");
ZVAL_NULL(rv);
return NULL;
} }
} }
break; break;
@@ -390,21 +449,21 @@ zval *php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj, zval *rv
case LUA_TTHREAD: case LUA_TTHREAD:
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
default: default:
php_error_docref(NULL, E_WARNING, "unsupported type '%s' for php", php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported type '%s' for php",
lua_typename(L, lua_type(L, index))); lua_typename(L, lua_type(L, index)));
ZVAL_NULL(rv);
return NULL;
} }
return rv;
return retval;
} }
/* }}} */ /* }}} */
int php_lua_send_zval_to_lua(lua_State *L, zval *val) /* {{{ */ { /** {{{ int php_lua_send_zval_to_lua(lua_State *L, zval *val TSRMLS_DC)
*/
int php_lua_send_zval_to_lua(lua_State *L, zval *val TSRMLS_DC) {
switch (Z_TYPE_P(val)) { switch (Z_TYPE_P(val)) {
case IS_TRUE: case IS_BOOL:
case IS_FALSE: lua_pushboolean(L, Z_BVAL_P(val));
lua_pushboolean(L, Z_LVAL_P(val));
break; break;
case IS_NULL: case IS_NULL:
lua_pushnil(L); lua_pushnil(L);
@@ -421,10 +480,10 @@ int php_lua_send_zval_to_lua(lua_State *L, zval *val) /* {{{ */ {
case IS_OBJECT: case IS_OBJECT:
case IS_ARRAY: case IS_ARRAY:
{ {
if (zend_is_callable(val, 0, NULL)) { if (zend_is_callable(val, 0, NULL TSRMLS_CC)) {
zval *callbacks; zval* callbacks = NULL;
callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1); callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1 TSRMLS_CC);
if (ZVAL_IS_NULL(callbacks)) { if (ZVAL_IS_NULL(callbacks)) {
array_init(callbacks); array_init(callbacks);
@@ -433,39 +492,57 @@ int php_lua_send_zval_to_lua(lua_State *L, zval *val) /* {{{ */ {
lua_pushnumber(L, zend_hash_num_elements(Z_ARRVAL_P(callbacks))); lua_pushnumber(L, zend_hash_num_elements(Z_ARRVAL_P(callbacks)));
lua_pushcclosure(L, php_lua_call_callback, 1); lua_pushcclosure(L, php_lua_call_callback, 1);
zval_add_ref(val); zval_add_ref(&val);
add_next_index_zval(callbacks, val); add_next_index_zval(callbacks, val);
} else { } else {
zval *v; HashTable *ht = NULL;
zend_string *key; zval **ppzval = NULL;
zval zkey;
HashTable *ht = HASH_OF(val); ht = HASH_OF(val);
if (++ht->u.v.nApplyCount > 1) {
php_error_docref(NULL, E_ERROR, "recursion found"); if (++ht->nApplyCount > 1) {
--ht->u.v.nApplyCount; php_error_docref(NULL TSRMLS_CC, E_ERROR, "recursion found");
--ht->nApplyCount;
break; break;
} }
lua_newtable(L); lua_newtable(L);
for(zend_hash_internal_pointer_reset(ht);
zend_hash_get_current_data(ht, (void **)&ppzval) == SUCCESS;
zend_hash_move_forward(ht)) {
char *key = NULL;
uint len = 0;
ulong idx = 0;
zval *zkey= NULL;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, v) { switch(zend_hash_get_current_key_ex(ht, &key, &len, &idx, 0, NULL)) {
if (Z_TYPE_P(v) == IS_STRING) { case HASH_KEY_IS_STRING :
ZVAL_STR(&zkey, key); MAKE_STD_ZVAL(zkey);
ZVAL_STRINGL(zkey, key, len - 1, 1);
break;
case HASH_KEY_IS_LONG:
if (idx == 0) {
php_error_docref(NULL TSRMLS_CC, E_STRICT,
"attempt to pass an array index begin with 0 to lua");
}
MAKE_STD_ZVAL(zkey);
ZVAL_LONG(zkey, idx);
break;
} }
if (Z_TYPE_P(v) == IS_LONG) {
ZVAL_LONG(&zkey, Z_LVAL_P(v)); php_lua_send_zval_to_lua(L, zkey TSRMLS_CC);
} php_lua_send_zval_to_lua(L, *ppzval TSRMLS_CC);
php_lua_send_zval_to_lua(L, &zkey);
php_lua_send_zval_to_lua(L, v);
lua_settable(L, -3); lua_settable(L, -3);
} ZEND_HASH_FOREACH_END();
--ht->u.v.nApplyCount; zval_ptr_dtor(&zkey);
}
--ht->nApplyCount;
} }
} }
break; break;
default: default:
php_error_docref(NULL, E_ERROR, "unsupported type `%s' for lua", zend_zval_type_name(val)); php_error_docref(NULL TSRMLS_CC, E_ERROR, "unsupported type `%s' for lua"
, zend_zval_type_name(val));
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
} }
@@ -474,49 +551,52 @@ int php_lua_send_zval_to_lua(lua_State *L, zval *val) /* {{{ */ {
} }
/* }}} */ /* }}} */
/*** {{{ static int php_lua_arg_apply_func(void *data, void *L) /*** {{{ static int php_lua_arg_apply_func(void *data, void *L TSRMLS_DC)
*/ */
static int php_lua_arg_apply_func(void *data, void *L) { static int php_lua_arg_apply_func(void *data, void *L TSRMLS_DC) {
php_lua_send_zval_to_lua((lua_State*)L, (zval*)data); php_lua_send_zval_to_lua((lua_State*)L, *(zval**)data TSRMLS_CC);
return ZEND_HASH_APPLY_KEEP; return ZEND_HASH_APPLY_KEEP;
} /* }}} */ } /* }}} */
static zval *php_lua_call_lua_function(zval *lua_obj, zval *func, zval *args, int use_self, zval *retval) /* {{{ */ { /** {{{ static zval * php_lua_call_lua_function(zval *lua_obj, zval *func, zval *args, int use_self TSRMLS_DC)
int bp = 0; */
int sp = 0; static zval * php_lua_call_lua_function(zval *lua_obj, zval *func, zval *args, int use_self TSRMLS_DC) {
int bp = 0;
int sp = 0;
int arg_num = 0; int arg_num = 0;
zval rv; zval *ret = NULL;
lua_State *L; lua_State *L = NULL;
L = (Z_LUAVAL_P(lua_obj))->L; L = Z_LUAVAL_P(lua_obj);
if (IS_ARRAY == Z_TYPE_P(func)) { if (IS_ARRAY == Z_TYPE_P(func)) {
zval *t, *f; zval **t = NULL;
if ((t = zend_hash_index_find(Z_ARRVAL_P(func), 0)) == NULL || Z_TYPE_P(t) != IS_STRING zval **f = NULL;
|| (f = zend_hash_index_find(Z_ARRVAL_P(func), 1)) == NULL || Z_TYPE_P(f) != IS_STRING) { if (zend_hash_index_find(Z_ARRVAL_P(func), 0, (void **)&t) == FAILURE || Z_TYPE_PP(t) != IS_STRING
|| zend_hash_index_find(Z_ARRVAL_P(func), 1, (void **)&f) == FAILURE || Z_TYPE_PP(f) != IS_STRING) {
/* as johannes suggesting use exceptioni to distinguish the error from a lua function return false /* as johannes suggesting use exceptioni to distinguish the error from a lua function return false
php_error_docref(NULL, E_WARNING, php_error_docref(NULL TSRMLS_CC, E_WARNING,
"invalid lua function, argument must be an array which contain two elements: array('table', 'method')"); "invalid lua function, argument must be an array which contain two elements: array('table', 'method')");
*/ */
zend_throw_exception_ex(lua_exception_ce, 0, zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC,
"invalid lua function, argument must be an array which contain two elements: array('table', 'method')"); "invalid lua function, argument must be an array which contain two elements: array('table', 'method')");
return NULL; return NULL;
} }
#if (LUA_VERSION_NUM < 502) #if (LUA_VERSION_NUM < 502)
lua_getfield(L, LUA_GLOBALSINDEX, Z_STRVAL_P(t)); lua_getfield(L, LUA_GLOBALSINDEX, Z_STRVAL_PP(t));
#else #else
lua_getglobal(L, Z_STRVAL_P(t)); lua_getglobal(L, Z_STRVAL_PP(t));
#endif #endif
if (LUA_TTABLE != lua_type(L, lua_gettop(L))) { if (LUA_TTABLE != lua_type(L, lua_gettop(L))) {
lua_pop(L, -1); lua_pop(L, -1);
zend_throw_exception_ex(lua_exception_ce, 0, "invalid lua table '%s'", Z_STRVAL_P(t)); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid lua table '%s'", Z_STRVAL_PP(t));
return NULL; return NULL;
} }
bp = lua_gettop(L); bp = lua_gettop(L);
lua_getfield(L, -1, Z_STRVAL_P(f)); lua_getfield(L, -1, Z_STRVAL_PP(f));
if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) { if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) {
lua_pop(L, -2); lua_pop(L, -2);
zend_throw_exception_ex(lua_exception_ce, 0, "invalid lua table function '%s'.%s", Z_STRVAL_P(t), Z_STRVAL_P(f)); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid lua table function '%s'.%s", Z_STRVAL_PP(t), Z_STRVAL_PP(f));
return NULL; return NULL;
} }
} else if (IS_STRING == Z_TYPE_P(func)) { } else if (IS_STRING == Z_TYPE_P(func)) {
@@ -528,21 +608,21 @@ static zval *php_lua_call_lua_function(zval *lua_obj, zval *func, zval *args, in
#endif #endif
if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) { if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) {
lua_pop(L, -1); lua_pop(L, -1);
zend_throw_exception_ex(lua_exception_ce, 0, "invalid lua function '%s'", Z_STRVAL_P(func)); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid lua function '%s'", Z_STRVAL_P(func));
return NULL; return NULL;
} }
} else if (IS_OBJECT == Z_TYPE_P(func) } else if (IS_OBJECT == Z_TYPE_P(func)
&& instanceof_function(Z_OBJCE_P(func), php_lua_get_closure_ce())) { && instanceof_function(Z_OBJCE_P(func), php_lua_get_closure_ce() TSRMLS_CC)) {
zval *closure = zend_read_property(php_lua_get_closure_ce(), func, ZEND_STRL("_closure"), 1, &rv); zval *closure = zend_read_property(php_lua_get_closure_ce(), func, ZEND_STRL("_closure"), 1 TSRMLS_CC);
if (!Z_LVAL_P(closure)) { if (!Z_LVAL_P(closure)) {
zend_throw_exception_ex(lua_exception_ce, 0, "invalid lua closure"); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid lua closure");
return NULL; return NULL;
} }
bp = lua_gettop(L); bp = lua_gettop(L);
lua_rawgeti(L, LUA_REGISTRYINDEX, Z_LVAL_P(closure)); lua_rawgeti(L, LUA_REGISTRYINDEX, Z_LVAL_P(closure));
if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) { if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) {
lua_pop(L, -1); lua_pop(L, -1);
zend_throw_exception_ex(lua_exception_ce, 0, "call to lua closure failed"); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "call to lua closure failed");
return NULL; return NULL;
} }
} }
@@ -555,11 +635,11 @@ static zval *php_lua_call_lua_function(zval *lua_obj, zval *func, zval *args, in
if (args) { if (args) {
arg_num += zend_hash_num_elements(Z_ARRVAL_P(args)); arg_num += zend_hash_num_elements(Z_ARRVAL_P(args));
zend_hash_apply_with_argument(Z_ARRVAL_P(args), (apply_func_arg_t)php_lua_arg_apply_func, (void *)L); zend_hash_apply_with_argument(Z_ARRVAL_P(args), php_lua_arg_apply_func, (void *)L TSRMLS_CC);
} }
if (lua_pcall(L, arg_num, LUA_MULTRET, 0) != LUA_OK) { if (lua_pcall(L, arg_num, LUA_MULTRET, 0) != LUA_OK) {
php_error_docref(NULL, E_WARNING, php_error_docref(NULL TSRMLS_CC, E_WARNING,
"call to lua function %s failed", lua_tostring(L, -1)); "call to lua function %s failed", lua_tostring(L, -1));
lua_pop(L, lua_gettop(L) - bp); lua_pop(L, lua_gettop(L) - bp);
return NULL; return NULL;
@@ -568,16 +648,17 @@ static zval *php_lua_call_lua_function(zval *lua_obj, zval *func, zval *args, in
sp = lua_gettop(L) - bp; sp = lua_gettop(L) - bp;
if (!sp) { if (!sp) {
ZVAL_NULL(retval); MAKE_STD_ZVAL(ret);
ZVAL_NULL(ret);
} else if (sp == 1) { } else if (sp == 1) {
php_lua_get_zval_from_lua(L, -1, lua_obj, retval); ret = php_lua_get_zval_from_lua(L, -1, lua_obj TSRMLS_CC);
} else { } else {
zval rv;
int i = 0; int i = 0;
array_init(retval); MAKE_STD_ZVAL(ret);
array_init(ret);
for (i = -sp; i < 0; i++) { for (i = -sp; i < 0; i++) {
php_lua_get_zval_from_lua(L, i, lua_obj, &rv); zval *tmp = php_lua_get_zval_from_lua(L, i, lua_obj TSRMLS_CC);
add_next_index_zval(retval, &rv); add_next_index_zval(ret, tmp);
} }
} }
@@ -587,43 +668,43 @@ static zval *php_lua_call_lua_function(zval *lua_obj, zval *func, zval *args, in
lua_pop(L, -1); lua_pop(L, -1);
} }
return retval; return ret;
} /* }}} */ } /* }}} */
/** {{{ proto Lua::eval(string $lua_chunk) /** {{{ proto Lua::eval(string $lua_chunk)
* eval a lua chunk * eval a lua chunk
*/ */
PHP_METHOD(lua, eval) { PHP_METHOD(lua, eval) {
lua_State *L; lua_State *L = NULL;
char *statements; char *statements = NULL;
long bp, len; long bp, len = 0;
int ret; int ret;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &statements, &len) == FAILURE) { L = Z_LUAVAL_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &statements, &len) == FAILURE) {
return; return;
} }
L = (Z_LUAVAL_P(getThis()))->L;
bp = lua_gettop(L); bp = lua_gettop(L);
if ((ret = luaL_loadbuffer(L, statements, len, "line")) != LUA_OK || (ret = lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK)) { if ((ret = luaL_loadbuffer(L, statements, len, "line")) != LUA_OK || (ret = lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK)) {
zend_throw_exception_ex(lua_exception_ce, ret, "%s", lua_tostring(L, -1)); zend_throw_exception_ex(lua_exception_ce, ret TSRMLS_CC, "%s", lua_tostring(L, -1));
lua_pop(L, 1); lua_pop(L, 1);
RETURN_FALSE; RETURN_FALSE;
} else { } else {
int ret_count; zval *tmp = NULL;
int ret_count = 0;
int i = 0;
ret_count = lua_gettop(L) - bp; ret_count = lua_gettop(L) - bp;
if (ret_count > 1) { if (ret_count > 1) {
zval rv;
int i = 0;
array_init(return_value); array_init(return_value);
for (i = -ret_count; i<0; i++) { for (i = -ret_count; i<0; i++) {
php_lua_get_zval_from_lua(L, i, getThis(), &rv); tmp = php_lua_get_zval_from_lua(L, i, getThis() TSRMLS_CC);
add_next_index_zval(return_value, &rv); add_next_index_zval(return_value, tmp);
} }
} else if (ret_count) { } else if (ret_count) {
php_lua_get_zval_from_lua(L, -1, getThis(), return_value); zval *tmp = php_lua_get_zval_from_lua(L, -1, getThis() TSRMLS_CC);
RETURN_ZVAL(tmp, 1, 1);
} }
lua_pop(L, ret_count); lua_pop(L, ret_count);
} }
@@ -634,41 +715,50 @@ PHP_METHOD(lua, eval) {
* run a lua script file * run a lua script file
*/ */
PHP_METHOD(lua, include) { PHP_METHOD(lua, include) {
lua_State *L; lua_State *L = NULL;
char *file; char *file = NULL;
size_t bp, len; long bp, len = 0;
int ret; int ret;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &file, &len) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &len) == FAILURE) {
return; return;
} }
if (php_check_open_basedir(file)) { if (php_check_open_basedir(file TSRMLS_CC)
#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4)) || (PHP_MAJOR_VERSION < 5)
|| (PG(safe_mode)
&& !php_checkuid(file, "rb+", CHECKUID_CHECK_MODE_PARAM))
#endif
) {
RETURN_FALSE; RETURN_FALSE;
} }
L = (Z_LUAVAL_P(getThis()))->L; L = Z_LUAVAL_P(getThis());
bp = lua_gettop(L); bp = lua_gettop(L);
if ((ret = luaL_loadfile(L, file)) != LUA_OK || (ret = lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK)) { if ((ret = luaL_loadfile(L, file)) != LUA_OK || (ret = lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK)) {
zend_throw_exception_ex(lua_exception_ce, ret, "%s", lua_tostring(L, -1)); zend_throw_exception_ex(lua_exception_ce, ret TSRMLS_CC, "%s", lua_tostring(L, -1));
lua_pop(L, 1); lua_pop(L, 1);
RETURN_FALSE; RETURN_FALSE;
} else { } else {
int ret_count; zval *tmp = NULL;
int ret_count = 0;
int i = 0;
ret_count = lua_gettop(L) - bp; ret_count = lua_gettop(L) - bp;
if (ret_count > 1) { if (ret_count > 1) {
zval rv;
int i = 0;
array_init(return_value); array_init(return_value);
for (i = -ret_count; i<0; i++) { for (i = -ret_count; i<0; i++) {
php_lua_get_zval_from_lua(L, i, getThis(), &rv); tmp = php_lua_get_zval_from_lua(L, i, getThis() TSRMLS_CC);
add_next_index_zval(return_value, &rv); add_next_index_zval(return_value, tmp);
} }
} else if (ret_count) { } else if (ret_count) {
php_lua_get_zval_from_lua(L, -1, getThis(), return_value); zval *tmp = php_lua_get_zval_from_lua(L, -1, getThis() TSRMLS_CC);
RETURN_ZVAL(tmp, 1, 1);
} }
lua_pop(L, ret_count); lua_pop(L, ret_count);
} }
} }
@@ -678,37 +768,41 @@ PHP_METHOD(lua, include) {
*/ */
PHP_METHOD(lua, call) { PHP_METHOD(lua, call) {
long u_self = 0; long u_self = 0;
zval *func;
zval *args = NULL; zval *args = NULL;
zval *func = NULL;
zval *ret = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|al", &func, &args, &u_self) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|al", &func, &args, &u_self) == FAILURE) {
return; return;
} }
if (!(php_lua_call_lua_function(getThis(), func, args, u_self, return_value))) { if ((ret = php_lua_call_lua_function(getThis(), func, args, u_self TSRMLS_CC))) {
RETURN_FALSE; RETURN_ZVAL(ret, 1, 1);
} }
RETURN_FALSE;
} }
/* }}} */ /* }}} */
/** {{{ proto Lua::assign(string $name, mix $value) /** {{{ proto Lua::assign(string $name, mix $value)
*/ */
PHP_METHOD(lua, assign) { PHP_METHOD(lua, assign) {
zval *name; char *name = NULL;
zval *value; zval *value = NULL;
lua_State *L; lua_State *L = NULL;
int len = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &name, &value) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &len, &value) == FAILURE) {
return; return;
} }
L = (Z_LUAVAL_P(getThis()))->L; L = Z_LUAVAL_P(getThis());
php_lua_send_zval_to_lua(L, value); php_lua_send_zval_to_lua(L, value TSRMLS_CC);
#if (LUA_VERSION_NUM < 502) #if (LUA_VERSION_NUM < 502)
lua_setfield(L, LUA_GLOBALSINDEX, Z_STRVAL_P(name)); lua_setfield(L, LUA_GLOBALSINDEX, name);
#else #else
lua_setglobal(L, Z_STRVAL_P(name)); lua_setglobal(L, name);
#endif #endif
RETURN_ZVAL(getThis(), 1, 0); RETURN_ZVAL(getThis(), 1, 0);
@@ -718,34 +812,33 @@ PHP_METHOD(lua, assign) {
/** {{{ proto Lua::registerCallback(string $name, mix $value) /** {{{ proto Lua::registerCallback(string $name, mix $value)
*/ */
PHP_METHOD(lua, registerCallback) { PHP_METHOD(lua, registerCallback) {
char *name; char *name = NULL;
size_t len; long len = 0;
zval *func; zval *func = NULL;
lua_State *L; lua_State *L = NULL;
zval* callbacks; zval* callbacks = NULL;
L = Z_LUAVAL_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS(),"sz", &name, &len, &func) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"sz", &name, &len, &func) == FAILURE) {
return; return;
} }
L = (Z_LUAVAL_P(getThis()))->L; callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1 TSRMLS_CC);
callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1);
if (ZVAL_IS_NULL(callbacks)) { if (ZVAL_IS_NULL(callbacks)) {
array_init(callbacks); array_init(callbacks);
} }
if (zend_is_callable(func, 0, NULL)) { if (zend_is_callable(func, 0, NULL TSRMLS_CC)) {
lua_pushnumber(L, zend_hash_num_elements(Z_ARRVAL_P(callbacks))); lua_pushnumber(L, zend_hash_num_elements(Z_ARRVAL_P(callbacks)));
lua_pushcclosure(L, php_lua_call_callback, 1); lua_pushcclosure(L, php_lua_call_callback, 1);
lua_setglobal(L, name); lua_setglobal(L, name);
} else { } else {
zend_throw_exception_ex(lua_exception_ce, 0, "invalid php callback"); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid php callback");
RETURN_FALSE; RETURN_FALSE;
} }
zval_add_ref(func); zval_add_ref(&func);
add_next_index_zval(callbacks, func); add_next_index_zval(callbacks, func);
RETURN_ZVAL(getThis(), 1, 0); RETURN_ZVAL(getThis(), 1, 0);
@@ -755,15 +848,14 @@ PHP_METHOD(lua, registerCallback) {
/** {{{ proto Lua::getVersion() /** {{{ proto Lua::getVersion()
*/ */
PHP_METHOD(lua, getVersion) { PHP_METHOD(lua, getVersion) {
RETURN_STRING(LUA_RELEASE); RETURN_STRING(LUA_RELEASE, 1);
} }
/* }}} */ /* }}} */
/** {{{ proto Lua::__construct() /** {{{ proto Lua::__construct()
*/ */
PHP_METHOD(lua, __construct) { PHP_METHOD(lua, __construct) {
lua_State * L = (Z_LUAVAL_P(getThis()))->L; lua_State *L = Z_LUAVAL_P(getThis());
luaL_openlibs(L); luaL_openlibs(L);
lua_register(L, "print", php_lua_print); lua_register(L, "print", php_lua_print);
if (ZEND_NUM_ARGS()) { if (ZEND_NUM_ARGS()) {
@@ -807,27 +899,28 @@ PHP_MINIT_FUNCTION(lua) {
REGISTER_LONG_CONSTANT("LUA_ERRFILE", LUA_ERRFILE, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LUA_ERRFILE", LUA_ERRFILE, CONST_PERSISTENT | CONST_CS);
lua_ce = zend_register_internal_class(&ce); lua_ce = zend_register_internal_class(&ce TSRMLS_CC);
lua_ce->create_object = php_lua_create_object; lua_ce->create_object = php_lua_create_object;
memcpy(&lua_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); memcpy(&lua_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
lua_object_handlers.offset = XtOffsetOf(php_lua_object, obj);
lua_object_handlers.dtor_obj = php_lua_dtor_object;
lua_object_handlers.free_obj = NULL;
lua_object_handlers.clone_obj = NULL;
lua_object_handlers.write_property = php_lua_write_property; lua_object_handlers.write_property = php_lua_write_property;
lua_object_handlers.read_property = php_lua_read_property; lua_object_handlers.read_property = php_lua_read_property;
lua_ce->ce_flags |= ZEND_ACC_FINAL; lua_ce->ce_flags |= ZEND_ACC_FINAL;
zend_declare_property_null(lua_ce, ZEND_STRL("_callbacks"), ZEND_ACC_STATIC|ZEND_ACC_PRIVATE); zend_declare_property_null(lua_ce, ZEND_STRL("_callbacks"), ZEND_ACC_STATIC|ZEND_ACC_PRIVATE TSRMLS_CC);
zend_declare_class_constant_string(lua_ce, ZEND_STRL("LUA_VERSION"), LUA_RELEASE); zend_declare_class_constant_string(lua_ce, ZEND_STRL("LUA_VERSION"), LUA_RELEASE TSRMLS_CC);
php_lua_closure_register(); php_lua_closure_register(TSRMLS_C);
INIT_CLASS_ENTRY(ce, "LuaException", NULL); INIT_CLASS_ENTRY(ce, "LuaException", NULL);
lua_exception_ce = zend_register_internal_class_ex(&ce,
lua_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default()); #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2)
zend_exception_get_default(),
#else
zend_exception_get_default(TSRMLS_C),
#endif
NULL TSRMLS_CC);
return SUCCESS; return SUCCESS;
} }

View File

@@ -11,10 +11,10 @@
| license@php.net so we can mail you a copy immediately. | | license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
| Author : Johannes Schlueter <johannes@php.net> | | Author : Johannes Schlueter <johannes@php.net> |
| Xinchen Hui <laruence@php.net> | | Xinchen Hui <laruence@php.net> |
| Marcelo Araujo <msaraujo@php.net> | | Marcelo Araujo <msaraujo@php.net> |
| Helmut Januschka <helmut@januschka.com> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
$Id: lua_closure.c 319740 2011-11-24 08:06:48Z laruence $
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@@ -43,12 +43,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_invoke, 0, 0, 1)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
/* }}} */ /* }}} */
/** {{{ zval * php_lua_closure_instance(zval *instance, long ref_id, zval *lua_obj) /** {{{ zval * php_lua_closure_instance(zval *instance, long ref_id, zval *lua_obj TSRMLS_DC)
*/ */
zval * php_lua_closure_instance(zval *instance, long ref_id, zval *lua_obj) { zval * php_lua_closure_instance(zval *instance, long ref_id, zval *lua_obj TSRMLS_DC) {
object_init_ex(instance, lua_closure_ce); object_init_ex(instance, lua_closure_ce);
zend_update_property_long(lua_closure_ce, instance, ZEND_STRL("_closure"), ref_id); zend_update_property_long(lua_closure_ce, instance, ZEND_STRL("_closure"), ref_id TSRMLS_CC);
zend_update_property(lua_closure_ce, instance, ZEND_STRL("_lua_object"), lua_obj); zend_update_property(lua_closure_ce, instance, ZEND_STRL("_lua_object"), lua_obj TSRMLS_CC);
return instance; return instance;
} }
@@ -63,21 +63,21 @@ PHP_METHOD(lua_closure, __construct) {
/** {{{ proto LuaClosure::__destruct() /** {{{ proto LuaClosure::__destruct()
*/ */
PHP_METHOD(lua_closure, __destruct) { PHP_METHOD(lua_closure, __destruct) {
zval *lua_obj, *closure, rv; zval *lua_obj, *closure;
lua_obj = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_lua_object"), 1, &rv); lua_obj = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_lua_object"), 1 TSRMLS_CC);
if (ZVAL_IS_NULL(lua_obj) if (ZVAL_IS_NULL(lua_obj)
|| Z_TYPE_P(lua_obj) != IS_OBJECT || Z_TYPE_P(lua_obj) != IS_OBJECT
|| !instanceof_function(Z_OBJCE_P(lua_obj), lua_ce)) { || !instanceof_function(Z_OBJCE_P(lua_obj), lua_ce TSRMLS_CC)) {
RETURN_FALSE; RETURN_FALSE;
} }
closure = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_closure"), 1, &rv); closure = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_closure"), 1 TSRMLS_CC);
if (!Z_LVAL_P(closure)) { if (!Z_LVAL_P(closure)) {
RETURN_FALSE; RETURN_FALSE;
} }
luaL_unref((Z_LUAVAL_P(lua_obj))->L, LUA_REGISTRYINDEX, Z_LVAL_P(closure)); luaL_unref(Z_LUAVAL_P(lua_obj), LUA_REGISTRYINDEX, Z_LVAL_P(closure));
} }
/* }}} */ /* }}} */
@@ -85,50 +85,49 @@ PHP_METHOD(lua_closure, __destruct) {
*/ */
PHP_METHOD(lua_closure, invoke) { PHP_METHOD(lua_closure, invoke) {
int bp, sp; int bp, sp;
zval *arguments = NULL; zval ***arguments = NULL;
zval *lua_obj = NULL; zval *lua_obj = NULL;
lua_State *L = NULL; lua_State *L = NULL;
zval *closure = NULL; zval *closure = NULL;
zval rv;
if (ZEND_NUM_ARGS()) { if (ZEND_NUM_ARGS()) {
arguments = emalloc(sizeof(zval*) * ZEND_NUM_ARGS()); arguments = emalloc(sizeof(zval**) * ZEND_NUM_ARGS());
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) { if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
efree(arguments); efree(arguments);
zend_throw_exception_ex(NULL, 0, "cannot get arguments for calling closure"); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "cannot get arguments for calling closure");
return; return;
} }
} }
lua_obj = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_lua_object"), 1, &rv); lua_obj = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_lua_object"), 1 TSRMLS_CC);
if (ZVAL_IS_NULL(lua_obj) if (ZVAL_IS_NULL(lua_obj)
|| Z_TYPE_P(lua_obj) != IS_OBJECT || Z_TYPE_P(lua_obj) != IS_OBJECT
|| !instanceof_function(Z_OBJCE_P(lua_obj), lua_ce)) { || !instanceof_function(Z_OBJCE_P(lua_obj), lua_ce TSRMLS_CC)) {
zend_throw_exception_ex(NULL, 0, "corrupted Lua object"); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "corrupted Lua object");
return; return;
} }
closure = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_closure"), 1, &rv); closure = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_closure"), 1 TSRMLS_CC);
if (!Z_LVAL_P(closure)) { if (!Z_LVAL_P(closure)) {
zend_throw_exception_ex(NULL, 0, "invalid lua closure"); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid lua closure");
return; return;
} }
L = (Z_LUAVAL_P(lua_obj))->L; L = Z_LUAVAL_P(lua_obj);
bp = lua_gettop(L); bp = lua_gettop(L);
lua_rawgeti(L, LUA_REGISTRYINDEX, Z_LVAL_P(closure)); lua_rawgeti(L, LUA_REGISTRYINDEX, Z_LVAL_P(closure));
if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) { if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) {
lua_pop(L, -1); lua_pop(L, -1);
zend_throw_exception_ex(NULL, 0, "call to lua closure failed"); zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "call to lua closure failed");
return; return;
} }
if (ZEND_NUM_ARGS()) { if (ZEND_NUM_ARGS()) {
int i = 0; int i = 0;
for(;i<ZEND_NUM_ARGS();i++) { for(;i<ZEND_NUM_ARGS();i++) {
php_lua_send_zval_to_lua(L, &arguments[i]); php_lua_send_zval_to_lua(L, *(arguments[i]) TSRMLS_CC);
} }
} }
@@ -137,7 +136,7 @@ PHP_METHOD(lua_closure, invoke) {
efree(arguments); efree(arguments);
} }
lua_pop(L, lua_gettop(L) - bp); lua_pop(L, lua_gettop(L) - bp);
zend_throw_exception_ex(NULL, 0, zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC,
"call to lua function %s failed", lua_tostring(L, -1)); "call to lua function %s failed", lua_tostring(L, -1));
return; return;
} }
@@ -147,14 +146,14 @@ PHP_METHOD(lua_closure, invoke) {
if (!sp) { if (!sp) {
RETURN_NULL(); RETURN_NULL();
} else if (sp == 1) { } else if (sp == 1) {
php_lua_get_zval_from_lua(L, -1, lua_obj, return_value); zval *tmp = php_lua_get_zval_from_lua(L, -1, lua_obj TSRMLS_CC);
RETURN_ZVAL(tmp, 0, 0);
} else { } else {
zval rv;
int i = 0; int i = 0;
array_init(return_value); array_init(return_value);
for (i = -sp; i < 0; i++) { for (i = -sp; i < 0; i++) {
php_lua_get_zval_from_lua(L, i, lua_obj, &rv); zval *tmp = php_lua_get_zval_from_lua(L, i, lua_obj TSRMLS_CC);
add_next_index_zval(return_value, &rv); add_next_index_zval(return_value, tmp);
} }
} }
@@ -185,45 +184,52 @@ zend_function_entry lua_closure_methods[] = {
}; };
/* }}} */ /* }}} */
static void php_lua_closure_dtor_object(void *object, zend_object_handlers handle) /* {{{ */ static void php_lua_closure_dtor_object(void *object, zend_object_handle handle TSRMLS_DC) /* {{{ */
{ {
zend_object *obj = (zend_object*)object; zend_object *obj = (zend_object*)object;
zend_object_std_dtor(obj); zend_object_std_dtor(obj TSRMLS_CC);
efree(obj); efree(obj);
} /* }}} */ } /* }}} */
zend_object *php_lua_closure_create_object(zend_class_entry *ce) /* {{{ */ static zend_object_value php_lua_closure_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */
{ {
zend_object *intern; zend_object_value obj = {0};
zend_object *lua_closure_obj = NULL;
intern = emalloc(sizeof(zend_object)+ sizeof(zval) * (ce->default_properties_count - 1));
if (!intern) { lua_closure_obj = emalloc(sizeof(zend_object));
php_error_docref(NULL, E_ERROR, "alloc memory for lua object failed");
}
zend_object_std_init(intern, ce); zend_object_std_init(lua_closure_obj, ce TSRMLS_CC);
object_properties_init(intern, ce); #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4)
zend_hash_copy(lua_closure_obj->properties, &ce->default_properties,
#if (PHP_MINOR_VERSION < 4)
(copy_ctor_func_t) zval_add_ref,
#else
zval_copy_property_ctor(ce),
#endif
(void *)0, sizeof(zval *));
#elif (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION > 3)
object_properties_init(lua_closure_obj, ce);
#endif
intern->handlers = zend_get_std_object_handlers(); obj.handle = zend_objects_store_put(lua_closure_obj, php_lua_closure_dtor_object, NULL, NULL TSRMLS_CC);
obj.handlers = zend_get_std_object_handlers();
return intern;
return obj;
} /* }}} */ } /* }}} */
void php_lua_closure_register() /* {{{ */ void php_lua_closure_register(TSRMLS_D) /* {{{ */
{ {
zend_class_entry ce; zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "LuaClosure", lua_closure_methods); INIT_CLASS_ENTRY(ce, "LuaClosure", lua_closure_methods);
lua_closure_ce = zend_register_internal_class(&ce); lua_closure_ce = zend_register_internal_class(&ce TSRMLS_CC);
lua_closure_ce->create_object = php_lua_closure_create_object; lua_closure_ce->create_object = php_lua_closure_create_object;
lua_closure_ce->ce_flags |= ZEND_ACC_FINAL; lua_closure_ce->ce_flags |= ZEND_ACC_FINAL;
zend_declare_property_long(lua_closure_ce, ZEND_STRL("_closure"), 0, ZEND_ACC_PRIVATE); zend_declare_property_long(lua_closure_ce, ZEND_STRL("_closure"), 0, ZEND_ACC_PRIVATE TSRMLS_CC);
zend_declare_property_null(lua_closure_ce, ZEND_STRL("_lua_object"), ZEND_ACC_PRIVATE); zend_declare_property_null(lua_closure_ce, ZEND_STRL("_lua_object"), ZEND_ACC_PRIVATE TSRMLS_CC);
} /* }}} */ } /* }}} */

View File

@@ -11,18 +11,15 @@
| license@php.net so we can mail you a copy immediately. | | license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
| Author : Johannes Schlueter <johannes@php.net> | | Author : Johannes Schlueter <johannes@php.net> |
| Xinchen Hui <laruence@php.net> | | Xinchen Hui <laruence@php.net> |
| Marcelo Araujo <msaraujo@php.net> | | Marcelo Araujo <msaraujo@php.net> |
| Helmut Januschka <helmut@januschka.com> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
$Id: lua_closure.h 319733 2011-11-24 07:13:56Z laruence $
*/ */
#ifndef LUA_CLOSURE_H void php_lua_closure_register(TSRMLS_D);
#define LUA_CLOSURE_H
void php_lua_closure_register();
zend_class_entry *php_lua_get_closure_ce(); zend_class_entry *php_lua_get_closure_ce();
zval * php_lua_closure_instance(zval *instance, long ref_id, zval *lua_obj); zval * php_lua_closure_instance(zval *instance, long ref_id, zval *lua_obj TSRMLS_DC);
#endif
/* /*
* Local variables: * Local variables:

View File

@@ -23,17 +23,11 @@
<email>msaraujo@php.net</email> <email>msaraujo@php.net</email>
<active>yes</active> <active>yes</active>
</developer> </developer>
<developer> <date>2013-10-23</date>
<name>Helmut Januschka</name> <time>12:04:27</time>
<user>hjanuschka</user>
<email>helmut@januschka.com</email>
<active>yes</active>
</developer>
<date>2015-10-27</date>
<time>11:12:27</time>
<version> <version>
<release>2.0.0</release> <release>1.1.0</release>
<api>2.0.0</api> <api>1.1.0</api>
</version> </version>
<stability> <stability>
<release>beta</release> <release>beta</release>
@@ -41,7 +35,9 @@
</stability> </stability>
<license uri="http://www.php.net/license">PHP</license> <license uri="http://www.php.net/license">PHP</license>
<notes> <notes>
- Release lua for PHP7 - Fixed #65097 (nApplyCount release missing) (emptyhua at gmail dot com)
- Trigger E_STRICT when pass an array with index '0' to lua instead of ignoring it
- added support for callable functions and closures as values returned injected into lua engine (harald at octris dot org)
</notes> </notes>
<contents> <contents>
<dir name="/"> <dir name="/">
@@ -75,7 +71,7 @@
<dependencies> <dependencies>
<required> <required>
<php> <php>
<min>7.0.0</min> <min>5.1.0</min>
</php> </php>
<pearinstaller> <pearinstaller>
<min>1.4.0</min> <min>1.4.0</min>
@@ -85,22 +81,6 @@
<providesextension>lua</providesextension> <providesextension>lua</providesextension>
<extsrcrelease /> <extsrcrelease />
<changelog> <changelog>
<release>
<date>2015-10-27</date>
<version>
<release>2.0.0</release>
<api>2.0.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
- Release lua for PHP7
</notes>
</release>
<release> <release>
<date>2012-10-23</date> <date>2012-10-23</date>
<version> <version>
@@ -118,6 +98,7 @@
- added support for callable functions and closures as values returned injected into lua engine (harald at octris dot org) - added support for callable functions and closures as values returned injected into lua engine (harald at octris dot org)
</notes> </notes>
</release> </release>
<release> <release>
<date>2012-06-24</date> <date>2012-06-24</date>
<version> <version>

View File

@@ -13,8 +13,8 @@
| Author : Johannes Schlueter <johannes@php.net> | | Author : Johannes Schlueter <johannes@php.net> |
| Xinchen Hui <laruence@php.net> | | Xinchen Hui <laruence@php.net> |
| Marcelo Araujo <msaraujo@php.net> | | Marcelo Araujo <msaraujo@php.net> |
| Helmut Januschka <helmut@januschka.com> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
$Id: php_lua.h 324349 2012-03-19 03:17:15Z laruence $
*/ */
#ifndef PHP_LUA_H #ifndef PHP_LUA_H
@@ -48,23 +48,24 @@ extern zend_module_entry lua_module_entry;
#define LUA_G(v) (lua_globals.v) #define LUA_G(v) (lua_globals.v)
#endif #endif
#define PHP_LUA_VERSION "2.0.0" #if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3)) || (PHP_MAJOR_VERSION < 5)
#define Z_ADDREF_P ZVAL_ADDREF
#define Z_REFCOUNT_P ZVAL_REFCOUNT
#define Z_DELREF_P ZVAL_DELREF
#endif
#define PHP_LUA_VERSION "1.1.1-dev"
#define Z_LUAVAL_P(obj) ((php_lua_object*)(zend_object_store_get_object(obj TSRMLS_CC)))->L
struct _php_lua_object { struct _php_lua_object {
lua_State *L; zend_object obj;
zend_object obj; lua_State *L;
}; };
typedef struct _php_lua_object php_lua_object; typedef struct _php_lua_object php_lua_object;
static inline php_lua_object *php_lua_obj_from_obj(zend_object *obj) { zval * php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj TSRMLS_DC);
return (php_lua_object*)((char*)(obj)-XtOffsetOf(php_lua_object, obj)); int php_lua_send_zval_to_lua(lua_State *L, zval *val TSRMLS_DC);
}
#define Z_LUAVAL_P(obj) php_lua_obj_from_obj(Z_OBJ_P((obj)))
zval *php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj, zval *rv);
int php_lua_send_zval_to_lua(lua_State *L, zval *val);
PHP_MINIT_FUNCTION(lua); PHP_MINIT_FUNCTION(lua);
PHP_MSHUTDOWN_FUNCTION(lua); PHP_MSHUTDOWN_FUNCTION(lua);
@@ -73,9 +74,9 @@ PHP_MINFO_FUNCTION(lua);
PHP_METHOD(lua, __construct); PHP_METHOD(lua, __construct);
PHP_METHOD(lua, eval); PHP_METHOD(lua, eval);
PHP_METHOD(lua, require); PHP_METHOD(lua, require);
#endif /* PHP_LUA_H */ #endif /* PHP_LUA_H */
/* /*
* Local variables: * Local variables:
* tab-width: 4 * tab-width: 4

2
tests/001.phpt Executable file → Normal file
View File

@@ -15,8 +15,6 @@ try {
assert($e->getCode() == LUA_ERRSYNTAX); assert($e->getCode() == LUA_ERRSYNTAX);
echo "\n", $e->getMessage(); echo "\n", $e->getMessage();
} }
?>
--EXPECTF-- --EXPECTF--
12 12
-0.53657291800043 -0.53657291800043

View File

@@ -1,30 +0,0 @@
--TEST--
Check for Table Pass vic-a-verse
--SKIPIF--
<?php if (!extension_loaded("lua")) print "skip"; ?>
--FILE--
<?php
$l = new lua();
$l->eval(<<<CODE
function test(a)
lua_fcn(a)
end
CODE
);
$l->registerCallback("lua_fcn", function($a) {
ksort($a);
var_dump($a);
});
$l->test(array("key1"=>"v1",
"key2"=>"v2"));
--EXPECT--
array(2) {
["key1"]=>
string(2) "v1"
["key2"]=>
string(2) "v2"
}

View File

@@ -1,7 +0,0 @@
#!/bin/sh
#exit 1 on error
echo "all ok ";
ls ./modules/bartlby.so
exit $?

View File

@@ -1,14 +1,2 @@
phpize #!/bin/sh
phpize && ./configure --with-lua-version=5.2 && make
./configure --with-lua-version=5.2
make
EX=$?;
if [ $EX != 0 ];
then
echo "compile failed";
exit $EX;
fi;
exit $EX;