From 5534b3252d1036a122c4f105b1b64ee598036529 Mon Sep 17 00:00:00 2001 From: laruence Date: Tue, 13 Dec 2011 17:04:44 +0800 Subject: [PATCH] initial commit --- CREDITS | 4 + EXPERIMENTAL | 2 + README | 2 + config.m4 | 48 +++ config.w32 | 15 + lua.c | 908 +++++++++++++++++++++++++++++++++++++++++++++++++ lua.php | 21 ++ lua_closure.c | 249 ++++++++++++++ lua_closure.h | 31 ++ package.xml | 66 ++++ package2.xml | 119 +++++++ php_lua.h | 78 +++++ tests/001.phpt | 16 + tests/002.phpt | 19 ++ tests/003.phpt | 95 ++++++ tests/004.phpt | 35 ++ tests/005.phpt | 17 + tests/006.phpt | 39 +++ tests/007.phpt | 30 ++ tests/008.phpt | 41 +++ tests/009.phpt | 45 +++ tests/010.phpt | 34 ++ tests/011.phpt | 18 + 23 files changed, 1932 insertions(+) create mode 100644 CREDITS create mode 100644 EXPERIMENTAL create mode 100644 README create mode 100644 config.m4 create mode 100644 config.w32 create mode 100644 lua.c create mode 100644 lua.php create mode 100644 lua_closure.c create mode 100644 lua_closure.h create mode 100644 package.xml create mode 100644 package2.xml create mode 100644 php_lua.h create mode 100644 tests/001.phpt create mode 100644 tests/002.phpt create mode 100644 tests/003.phpt create mode 100644 tests/004.phpt create mode 100644 tests/005.phpt create mode 100644 tests/006.phpt create mode 100644 tests/007.phpt create mode 100644 tests/008.phpt create mode 100644 tests/009.phpt create mode 100644 tests/010.phpt create mode 100644 tests/011.phpt diff --git a/CREDITS b/CREDITS new file mode 100644 index 0000000..1d43974 --- /dev/null +++ b/CREDITS @@ -0,0 +1,4 @@ +lua +Johannes Schlueter +Marcelo Araujo +Xinchen Hui diff --git a/EXPERIMENTAL b/EXPERIMENTAL new file mode 100644 index 0000000..6c9c970 --- /dev/null +++ b/EXPERIMENTAL @@ -0,0 +1,2 @@ +This extension embeds lua interpreter into PHP. We should emphasize that is +still under development and is completely experimental. diff --git a/README b/README new file mode 100644 index 0000000..2825319 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +"Lua is a powerful, fast, light-weight, embeddable scripting language." +This extension embeds the lua interpreter and offers an OO-API to lua variables and functions. diff --git a/config.m4 b/config.m4 new file mode 100644 index 0000000..6194583 --- /dev/null +++ b/config.m4 @@ -0,0 +1,48 @@ +dnl $Id: config.m4 315592 2011-08-27 00:58:41Z johannes $ +PHP_ARG_WITH(lua, for lua support, +[ --with-lua=[DIR] Include php lua support]) + +if test "$PHP_LUA" != "no"; then + if test -r $PHP_LUA/include/lua.h; then + LUA_DIR=$PHP_LUA + else + AC_MSG_CHECKING(for lua in default path) + for i in /usr/local /usr; do + if test -r $i/include/lua/include.h; then + LUA_DIR=$i + AC_MSG_RESULT(found in $i) + break + fi + done + fi + + if test -z "$LUA_DIR"; then + AC_MSG_RESULT(not found) + AC_MSG_ERROR(Please reinstall the lua distribution - lua.h should be in /include/) + fi + + LUA_LIB_NAME=lua + + if test -r $PHP_LUA/$PHP_LIBDIR/lib${LUA_LIB_NAME}.a; then + LUA_LIB_DIR=$PHP_LUA/$PHP_LIBDIR + else + AC_MSG_CHECKING(for lua library in default path) + for i in /usr/lib /usr/lib64; do + if test -r $i/$PHP_LIBDIR/${LUA_LIB_DIR}.a; then + LUA_LIB_DIR=$i + AC_MSG_RESULT(found in $i) + break + fi + done + fi + + if test -z "$LUA_LIB_DIR"; then + AC_MSG_RESULT(not found) + AC_MSG_ERROR(Please reinstall the lua distribution - lua library should be in /lib/) + fi + + PHP_ADD_INCLUDE($LUA_DIR/include) + PHP_ADD_LIBRARY_WITH_PATH(lua, $LUA_LIB_DIR, LUA_SHARED_LIBADD) + PHP_SUBST(LUA_SHARED_LIBADD) + PHP_NEW_EXTENSION(lua, lua.c lua_closure.c, $ext_shared) +fi diff --git a/config.w32 b/config.w32 new file mode 100644 index 0000000..9f7375a --- /dev/null +++ b/config.w32 @@ -0,0 +1,15 @@ +// $Id: config.w32 314169 2011-08-03 14:05:16Z laruence $ +// vim:ft=javascript + +ARG_WITH("lua", "lua support", "no"); + +if (PHP_LUA != "no") { + if (CHECK_LIB("liblua.lib", "lua", PHP_LUA) && + CHECK_HEADER_ADD_INCLUDE("lua.h", "CFLAGS_LUA", + PHP_LUA + "\\include;" + PHP_PHP_BUILD + "\\include\\lua;" + PHP_LUA)) { + EXTENSION("lua", "lua.c"); + AC_DEFINE('HAVE_LUA', 1, 'Have LUA library'); + } else { + WARNING("lua not enabled; libraries and headers not found"); + } +} diff --git a/lua.c b/lua.c new file mode 100644 index 0000000..191027c --- /dev/null +++ b/lua.c @@ -0,0 +1,908 @@ +/* + +----------------------------------------------------------------------+ + | Lua | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author : Johannes Schlueter | + | Xinchen Hui | + | Marcelo Araujo | + +----------------------------------------------------------------------+ + $Id: lua.c 319740 2011-11-24 08:06:48Z laruence $ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "Zend/zend_exceptions.h" +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "php_lua.h" +#include "lua_closure.h" + +zend_class_entry *lua_ce; +zend_class_entry *lua_exception_ce; +static zend_object_handlers lua_object_handlers; + +/** {{{ ARG_INFO + * + */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call, 0, 0, 2) + ZEND_ARG_INFO(0, method) + ZEND_ARG_INFO(0, args) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_assign, 0, 0, 2) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_register, 0, 0, 2) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, function) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_include, 0, 0, 1) + ZEND_ARG_INFO(0, file) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_eval, 0, 0, 1) + ZEND_ARG_INFO(0, statements) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_free, 0, 0, 1) + ZEND_ARG_INFO(0, closure) +ZEND_END_ARG_INFO() +/* }}} */ + +/* {{{ lua_module_entry +*/ +zend_module_entry lua_module_entry = { +#if ZEND_MODULE_API_NO >= 20010901 + STANDARD_MODULE_HEADER, +#endif + "lua", + NULL, + PHP_MINIT(lua), + PHP_MSHUTDOWN(lua), + NULL, + NULL, + PHP_MINFO(lua), +#if ZEND_MODULE_API_NO >= 20010901 + PHP_LUA_VERSION, +#endif + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_LUA +ZEND_GET_MODULE(lua) +#endif + +/** {{{ static void php_lua_stack_dump(lua_State* L) + * just for debug + */ +#ifdef PHP_LUA_DEBUG +static void php_lua_stack_dump(lua_State* L) { + int i = 1; + int n = lua_gettop(L); + printf("The Length of stack is %d\n", n); + for (; i <= n; ++i) { + int t = lua_type(L, i); + printf("%s:", lua_typename(L, t)); + switch(t) { + case LUA_TNUMBER: + printf("%f", lua_tonumber(L, i)); + break; + case LUA_TSTRING: + printf("%s", lua_tostring(L, i)); + break; + case LUA_TTABLE: + break; + case LUA_TFUNCTION: + break; + case LUA_TNIL: + printf("NULL"); + break; + case LUA_TBOOLEAN: + printf("%s", lua_toboolean(L, i) ? "TRUE" : "FALSE"); + break; + default: + break; + } + printf("\n"); + } +} +#endif +/* }}} */ + +/** {{{ static int php_lua_atpanic(lua_State *L) +*/ +static int php_lua_atpanic(lua_State *L) { + TSRMLS_FETCH(); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "lua panic (%s)", lua_tostring(L, 1)); + lua_pop(L, 1); + zend_bailout(); + return 0; +} +/* }}} */ + +/** {{{ static int php_lua_print(lua_State *L) +*/ +static int php_lua_print(lua_State *L) { + int i = 0; + + TSRMLS_FETCH(); + for (i = -lua_gettop(L) ; i<0; i++) { + zval *tmp = php_lua_get_zval_from_lua(L, i, NULL TSRMLS_CC); + zend_print_zval_r(tmp, 1 TSRMLS_CC); + zval_ptr_dtor(&tmp); + } + return 0; +} +/* }}} */ + +/** {{{ static void * php_lua_alloc_function(void *ud, void *ptr, size_t osize, size_t nsize) + * the memory-allocation function used by Lua states. + */ +static void * php_lua_alloc_function(void *ud, void *ptr, size_t osize, size_t nsize) { + (void) osize; + (void) nsize; + + if (nsize) { + if (ptr) { + return erealloc(ptr, nsize); + } + return emalloc(nsize); + } else { + if (ptr) { + efree(ptr); + } + } + + return NULL; +} +/* }}} */ + +/** {{{ static void php_lua_dtor_object(void *object, zend_object_handle handle TSRMLS_DC) + * 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) TSRMLS_CC); + + if (lua_obj->L) { + lua_close(lua_obj->L); + } + + efree(lua_obj); +} +/* }}} */ + +/** {{{ static zend_object_value php_lua_create_object(zend_class_entry *ce TSRMLS_DC) + * + * the create object handler for lua + */ +static zend_object_value php_lua_create_object(zend_class_entry *ce TSRMLS_DC) { + zend_object_value obj = {0}; + php_lua_object *lua_obj = NULL; + lua_State *L = NULL; + + L = lua_newstate(php_lua_alloc_function, NULL); + + lua_atpanic(L, php_lua_atpanic); + + lua_obj = emalloc(sizeof(php_lua_object)); + + if (!lua_obj) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "alloc memory for lua object failed"); + } + + lua_obj->L = L; + zend_object_std_init(&(lua_obj->obj), ce TSRMLS_CC); + +#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4) + zend_hash_copy(lua_obj->obj.properties, &ce->default_properties, +#if (PHP_MINOR_VERSION < 3) + (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 + + obj.handle = zend_objects_store_put(lua_obj, php_lua_dtor_object, NULL, NULL TSRMLS_CC); + obj.handlers = &lua_object_handlers; + + return obj; +} +/* }}} */ + +/** {{{ static zval * php_lua_read_property(zval *object, zval *member, int type TSRMLS_DC) +*/ +#if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 4)) || (PHP_MAJOR_VERSION < 5) +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) { + (void)key; +#endif + zval *retval = NULL; + lua_State *L = NULL; + zval *tmp_member = NULL; + + if (type != BP_VAR_R) { + MAKE_STD_ZVAL(retval); + ZVAL_NULL(retval); + return retval; + } + + if (Z_TYPE_P(member) != IS_STRING) { + ALLOC_ZVAL(tmp_member); + *tmp_member = *member; + INIT_PZVAL(tmp_member); + zval_copy_ctor(tmp_member); + convert_to_string(tmp_member); + member = tmp_member; + } + + L = Z_LUAVAL_P(object); + + lua_getfield(L, LUA_GLOBALSINDEX, Z_STRVAL_P(member)); + retval = php_lua_get_zval_from_lua(L, -1, object TSRMLS_CC); + Z_DELREF_P(retval); + lua_pop(L, 1); + + if (tmp_member) { + zval_ptr_dtor(&tmp_member); + } + + return retval; +} +/* }}} */ + +/** {{{ static void php_lua_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +*/ +#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) { + (void)key; +#endif + lua_State *L = NULL; + zval *tmp_member = NULL; + + if (Z_TYPE_P(member) != IS_STRING) { + ALLOC_ZVAL(tmp_member); + *tmp_member = *member; + INIT_PZVAL(tmp_member); + zval_copy_ctor(tmp_member); + convert_to_string(tmp_member); + member = tmp_member; + } + + L = Z_LUAVAL_P(object); + + php_lua_send_zval_to_lua(L, member TSRMLS_CC); + php_lua_send_zval_to_lua(L, value TSRMLS_CC); + + lua_settable(L, LUA_GLOBALSINDEX); + + if (tmp_member) { + zval_ptr_dtor(&tmp_member); + } +} +/* }}} */ + +/** {{{ 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)) { + case LUA_TNIL: + ZVAL_NULL(retval); + break; + case LUA_TBOOLEAN: + ZVAL_BOOL(retval, lua_toboolean(L, index)); + break; + case LUA_TNUMBER: + ZVAL_DOUBLE(retval, lua_tonumber(L, index)); + break; + case LUA_TSTRING: + { + char *val = NULL; + size_t len = 0; + + val = (char *)lua_tolstring(L, index, &len); + ZVAL_STRINGL(retval, val, len, 1); + } + break; + case LUA_TTABLE: + array_init(retval); + lua_pushnil(L); /* first key */ + while (lua_next(L, index-1) != 0) { + zval *key = NULL; + zval *val = NULL; + + /* uses 'key' (at index -2) and 'value' (at index -1) */ + key = php_lua_get_zval_from_lua(L, -2, lua_obj TSRMLS_CC); + val = php_lua_get_zval_from_lua(L, -1, lua_obj TSRMLS_CC); + + if (!key || !val) { + /* there is a warning already in php_lua_get_zval_from_lua */ + break; + } + + switch(Z_TYPE_P(key)) { + case IS_DOUBLE: + case IS_LONG: + add_index_zval(retval, Z_DVAL_P(key), val); + break; + case IS_STRING: + add_assoc_zval(retval, Z_STRVAL_P(key), val); + break; + case IS_ARRAY: + case IS_OBJECT: + default: + break; + } + lua_pop(L, 1); + zval_ptr_dtor(&key); + } + break; + case LUA_TFUNCTION: + { + long ref_id = 0; + if (!lua_obj) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "corrupted Lua object"); + break; + } + + lua_pushvalue(L, index); + ref_id = luaL_ref(L, LUA_REGISTRYINDEX); + + if (!php_lua_closure_instance(retval, ref_id, lua_obj TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to initialize closure object"); + } + } + break; + case LUA_TUSERDATA: + case LUA_TTHREAD: + case LUA_TLIGHTUSERDATA: + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported type '%s' for php", + lua_typename(L, lua_type(L, index))); + } + + return retval; +} +/* }}} */ + +/** {{{ 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)) { + case IS_BOOL: + lua_pushboolean(L, Z_BVAL_P(val)); + break; + case IS_NULL: + lua_pushnil(L); + break; + case IS_DOUBLE: + lua_pushnumber(L, Z_DVAL_P(val)); + break; + case IS_LONG: + lua_pushnumber(L, Z_LVAL_P(val)); + break; + case IS_STRING: + lua_pushlstring(L, Z_STRVAL_P(val), Z_STRLEN_P(val)); + break; + case IS_OBJECT: + case IS_ARRAY: + { + HashTable *ht = NULL; + zval **ppzval = NULL; + + ht = HASH_OF(val); + + if (++ht->nApplyCount > 1) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "recursion found"); + --ht->nApplyCount; + break; + } + + 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; + int len = 0; + long idx = 0; + zval *zkey= NULL; + + switch(zend_hash_get_current_key_ex(ht, &key, &len, &idx, 0, NULL)) { + case HASH_KEY_IS_STRING : + 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_NOTICE + , "attempt to pass an array index begin with 0 to lua, the index 0 will be discarded"); + continue; + } + MAKE_STD_ZVAL(zkey); + ZVAL_LONG(zkey, idx); + break; + } + + php_lua_send_zval_to_lua(L, zkey TSRMLS_CC); + php_lua_send_zval_to_lua(L, *ppzval TSRMLS_CC); + lua_settable(L, -3); + + zval_ptr_dtor(&zkey); + } + } + break; + default: + php_error_docref(NULL TSRMLS_CC, E_ERROR, "unsupported type `%s' for lua" + , zend_zval_type_name(val)); + lua_pushnil(L); + return 1; + } + + return 0; +} +/* }}} */ + +/*** {{{ static int php_lua_arg_apply_func(void *data, void *L TSRMLS_DC) +*/ +static int php_lua_arg_apply_func(void *data, void *L TSRMLS_DC) { + php_lua_send_zval_to_lua((lua_State*)L, *(zval**)data TSRMLS_CC); + return ZEND_HASH_APPLY_KEEP; +} /* }}} */ + +/** {{{ static int php_lua_call_callback(lua_State *L) +*/ +static int php_lua_call_callback(lua_State *L) { + int order = 0; + zval *return_value = NULL; + zval **func = NULL; + zval *callbacks = NULL; + order = lua_tonumber(L, lua_upvalueindex(1)); + + TSRMLS_FETCH(); + callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1 TSRMLS_CC); + + if (ZVAL_IS_NULL(callbacks)) { + return 0; + } + + 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; + } else { + zval **params = NULL; + int i = 0; + int arg_num = lua_gettop(L); + + params = ecalloc(arg_num, sizeof(zval)); + + for (; i 1) { + array_init(return_value); + for (i = -ret_count; i<0; i++) { + tmp = php_lua_get_zval_from_lua(L, i, getThis() TSRMLS_CC); + add_next_index_zval(return_value, tmp); + } + } else if (ret_count) { + zval *tmp = php_lua_get_zval_from_lua(L, -1, getThis() TSRMLS_CC); + RETURN_ZVAL(tmp, 1, 1); + } + lua_pop(L, ret_count); + } +} +/* }}} */ + +/** {{{ proto Lua::include(string $file) + * run a lua script file + */ +PHP_METHOD(lua, include) { + lua_State *L = NULL; + char *file = NULL; + long bp, len = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &len) == FAILURE) { + return; + } + + 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; + } + + L = Z_LUAVAL_P(getThis()); + + bp = lua_gettop(L); + if (luaL_dofile(L, file)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "lua error: %s", lua_tostring(L, -1)); + lua_pop(L, 1); + RETURN_FALSE; + } else { + zval *tmp = NULL; + int ret_count = 0; + int i = 0; + + ret_count = lua_gettop(L) - bp; + if (ret_count > 1) { + array_init(return_value); + + for (i = -ret_count; i<0; i++) { + tmp = php_lua_get_zval_from_lua(L, i, getThis() TSRMLS_CC); + add_next_index_zval(return_value, tmp); + } + + } else if (ret_count) { + zval *tmp = php_lua_get_zval_from_lua(L, -1, getThis() TSRMLS_CC); + RETURN_ZVAL(tmp, 1, 1); + } + + lua_pop(L, ret_count); + } +} +/* }}} */ + +/** {{{ proto Lua::call(mixed $function, array $args, bool $use_self) +*/ +PHP_METHOD(lua, call) { + long u_self = 0; + zval *args = NULL; + zval *func = NULL; + zval *ret = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|al", &func, &args, &u_self) == FAILURE) { + return; + } + + if ((ret = php_lua_call_lua_function(getThis(), func, args, u_self TSRMLS_CC))) { + RETURN_ZVAL(ret, 1, 1); + } + + RETURN_FALSE; +} +/* }}} */ + +/** {{{ proto Lua::assign(string $name, mix $value) +*/ +PHP_METHOD(lua, assign) { + char *name = NULL; + zval *value = NULL; + lua_State *L = NULL; + int len = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &len, &value) == FAILURE) { + return; + } + + L = Z_LUAVAL_P(getThis()); + + php_lua_send_zval_to_lua(L, value TSRMLS_CC); + lua_setfield(L, LUA_GLOBALSINDEX, name); + + RETURN_ZVAL(getThis(), 1, 0); +} +/* }}} */ + +/** {{{ proto Lua::registerCallback(string $name, mix $value) +*/ +PHP_METHOD(lua, registerCallback) { + char *name = NULL; + long len = 0; + zval *func = NULL; + lua_State *L = NULL; + zval* callbacks = NULL; + L = Z_LUAVAL_P(getThis()); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"sz", &name, &len, &func) == FAILURE) { + return; + } + + callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1 TSRMLS_CC); + + if (ZVAL_IS_NULL(callbacks)) { + array_init(callbacks); + } + + if (zend_is_callable(func, 0, NULL TSRMLS_CC)) { + lua_pushnumber(L, zend_hash_num_elements(Z_ARRVAL_P(callbacks))); + lua_pushcclosure(L, php_lua_call_callback, 1); + lua_setglobal(L, name); + } else { + zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid php callback"); + RETURN_FALSE; + } + + zval_add_ref(&func); + add_next_index_zval(callbacks, func); + + RETURN_ZVAL(getThis(), 1, 0); +} +/* }}} */ + +/** {{{ proto Lua::getVersion() +*/ +PHP_METHOD(lua, getVersion) { + RETURN_STRING(LUA_RELEASE, 1); +} +/* }}} */ + +/** {{{ proto Lua::__construct() +*/ +PHP_METHOD(lua, __construct) { + lua_State *L = Z_LUAVAL_P(getThis()); + luaL_openlibs(L); + lua_register(L, "print", php_lua_print); + if (ZEND_NUM_ARGS()) { + PHP_MN(lua_include)(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } +} +/* }}} */ + +/* {{{ lua_class_methods[] + * + */ +zend_function_entry lua_class_methods[] = { + PHP_ME(lua, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(lua, eval, arginfo_lua_eval, ZEND_ACC_PUBLIC) + PHP_ME(lua, include, arginfo_lua_include, ZEND_ACC_PUBLIC) + PHP_ME(lua, call, arginfo_lua_call, ZEND_ACC_PUBLIC) + PHP_ME(lua, assign, arginfo_lua_assign, ZEND_ACC_PUBLIC) + PHP_ME(lua, getVersion, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC) + PHP_ME(lua, registerCallback, arginfo_lua_register, ZEND_ACC_PUBLIC) + PHP_MALIAS(lua, __call, call, arginfo_lua_call, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION +*/ +PHP_MINIT_FUNCTION(lua) { + zend_class_entry ce; + + INIT_CLASS_ENTRY(ce, "Lua", lua_class_methods); + + lua_ce = zend_register_internal_class(&ce TSRMLS_CC); + lua_ce->create_object = php_lua_create_object; + memcpy(&lua_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + + lua_object_handlers.write_property = php_lua_write_property; + lua_object_handlers.read_property = php_lua_read_property; + + lua_ce->ce_flags |= ZEND_ACC_FINAL; + + 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 TSRMLS_CC); + + php_lua_closure_register(TSRMLS_C); + + INIT_CLASS_ENTRY(ce, "LuaException", NULL); + lua_exception_ce = zend_register_internal_class_ex(&ce, +#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; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION +*/ +PHP_MSHUTDOWN_FUNCTION(lua) +{ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION +*/ +PHP_MINFO_FUNCTION(lua) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "lua support", "enabled"); + php_info_print_table_row(2, "lua extension version", PHP_LUA_VERSION); + php_info_print_table_row(2, "lua release", LUA_RELEASE); + php_info_print_table_row(2, "lua copyright", LUA_COPYRIGHT); + php_info_print_table_row(2, "lua authors", LUA_AUTHORS); + php_info_print_table_end(); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/lua.php b/lua.php new file mode 100644 index 0000000..c5f8f20 --- /dev/null +++ b/lua.php @@ -0,0 +1,21 @@ +"; + +if(!extension_loaded('lua')) { + dl('lua.' . PHP_SHLIB_SUFFIX); +} +$module = 'lua'; +$functions = get_extension_funcs($module); +echo "Functions available in the test extension:$br\n"; +foreach($functions as $func) { + echo $func."$br\n"; +} +echo "$br\n"; +$function = 'confirm_' . $module . '_compiled'; +if (extension_loaded($module)) { + $str = $function($module); +} else { + $str = "Module $module is not compiled into PHP"; +} +echo "$str\n"; +?> diff --git a/lua_closure.c b/lua_closure.c new file mode 100644 index 0000000..ac17206 --- /dev/null +++ b/lua_closure.c @@ -0,0 +1,249 @@ +/* + +----------------------------------------------------------------------+ + | Lua | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author : Johannes Schlueter | + | Xinchen Hui | + | Marcelo Araujo | + +----------------------------------------------------------------------+ + $Id: lua_closure.c 319740 2011-11-24 08:06:48Z laruence $ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "Zend/zend_exceptions.h" + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +#include "php_lua.h" + +static zend_class_entry *lua_closure_ce; +extern zend_class_entry *lua_ce; +extern zend_class_entry *lua_exception_ce; + +/** {{{ ARG_INFO + * + */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_invoke, 0, 0, 1) + ZEND_ARG_INFO(0, arg) + ZEND_ARG_INFO(0, ...) +ZEND_END_ARG_INFO() +/* }}} */ + +/** {{{ 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 TSRMLS_DC) { + object_init_ex(instance, lua_closure_ce); + 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 TSRMLS_CC); + + return instance; +} +/** }}} */ + +/** {{{ proto LuaClosure::__construct() +*/ +PHP_METHOD(lua_closure, __construct) { +} +/* }}} */ + +/** {{{ proto LuaClosure::__destruct() +*/ +PHP_METHOD(lua_closure, __destruct) { + zval *lua_obj, *closure; + + lua_obj = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_lua_object"), 1 TSRMLS_CC); + if (ZVAL_IS_NULL(lua_obj) + || Z_TYPE_P(lua_obj) != IS_OBJECT + || !instanceof_function(Z_OBJCE_P(lua_obj), lua_ce TSRMLS_CC)) { + RETURN_FALSE; + } + + closure = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_closure"), 1 TSRMLS_CC); + if (!Z_LVAL_P(closure)) { + RETURN_FALSE; + } + + luaL_unref(Z_LUAVAL_P(lua_obj), LUA_REGISTRYINDEX, Z_LVAL_P(closure)); +} +/* }}} */ + +/** {{{ proto LuaClosure::invoke(mxied $args) +*/ +PHP_METHOD(lua_closure, invoke) { + int bp, sp; + zval ***arguments = NULL; + zval *lua_obj = NULL; + lua_State *L = NULL; + zval *closure = NULL; + + if (ZEND_NUM_ARGS()) { + arguments = emalloc(sizeof(zval**) * ZEND_NUM_ARGS()); + if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) { + efree(arguments); + zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "cannot get arguments for calling closure"); + return; + } + } + + lua_obj = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_lua_object"), 1 TSRMLS_CC); + + if (ZVAL_IS_NULL(lua_obj) + || Z_TYPE_P(lua_obj) != IS_OBJECT + || !instanceof_function(Z_OBJCE_P(lua_obj), lua_ce TSRMLS_CC)) { + zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "corrupted Lua object"); + return; + } + + closure = zend_read_property(lua_closure_ce, getThis(), ZEND_STRL("_closure"), 1 TSRMLS_CC); + if (!Z_LVAL_P(closure)) { + zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "invalid lua closure"); + return; + } + + L = Z_LUAVAL_P(lua_obj); + + bp = lua_gettop(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, Z_LVAL_P(closure)); + if (LUA_TFUNCTION != lua_type(L, lua_gettop(L))) { + lua_pop(L, -1); + zend_throw_exception_ex(lua_exception_ce, 0 TSRMLS_CC, "call to lua closure failed"); + return; + } + + if (ZEND_NUM_ARGS()) { + int i = 0; + for(;iproperties, &ce->default_properties, +#if (PHP_MINOR_VERSION < 3) + (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 + + 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 obj; +} /* }}} */ + +void php_lua_closure_register(TSRMLS_D) /* {{{ */ +{ + zend_class_entry ce; + + INIT_CLASS_ENTRY(ce, "LuaClosure", lua_closure_methods); + lua_closure_ce = zend_register_internal_class(&ce TSRMLS_CC); + lua_closure_ce->create_object = php_lua_closure_create_object; + lua_closure_ce->ce_flags |= ZEND_ACC_FINAL; + + 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 TSRMLS_CC); + + +} /* }}} */ + +zend_class_entry *php_lua_get_closure_ce() /* {{{ */ +{ + return lua_closure_ce; +} /* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/lua_closure.h b/lua_closure.h new file mode 100644 index 0000000..dba173f --- /dev/null +++ b/lua_closure.h @@ -0,0 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | Lua | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author : Johannes Schlueter | + | Xinchen Hui | + | Marcelo Araujo | + +----------------------------------------------------------------------+ + $Id: lua_closure.h 319733 2011-11-24 07:13:56Z laruence $ +*/ + +void php_lua_closure_register(TSRMLS_D); +zend_class_entry *php_lua_get_closure_ce(); +zval * php_lua_closure_instance(zval *instance, long ref_id, zval *lua_obj TSRMLS_DC); + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/package.xml b/package.xml new file mode 100644 index 0000000..a2961a7 --- /dev/null +++ b/package.xml @@ -0,0 +1,66 @@ + + + + lua + Embedded lua interpreter + "Lua is a powerful, fast, light-weight, embeddable scripting language." + This extension embeds the lua interpreter and offers an OO-API to lua variables and functions. + + + + johannes + Johannes Schlüter + johannes@php.net + lead + + + laruence + Xinchen Hui + laruence@php.net + lead + + + msaraujo + Marcelo Araujo + msaraujo@php.net + developer + + + + 0.9.1 + 2011-11-24 + PHP + beta + - Compatible with PHP5.3+ +- Fix ZTS build +- Fix mem leak when get value from lua + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package2.xml b/package2.xml new file mode 100644 index 0000000..321374c --- /dev/null +++ b/package2.xml @@ -0,0 +1,119 @@ + + + lua + pecl.php.net + Embedded lua interpreter + "Lua is a powerful, fast, light-weight, embeddable scripting language." + This extension embeds the lua interpreter and offers an OO-API to lua variables and functions. + + Johannes Schlüter + johannes + johannes@php.net + yes + + + Xinchen Hui + laruence + laruence@php.net + yes + + + Marcelo Araujo + msaraujo + msaraujo@php.net + yes + + 2011-11-24 + + + 0.9.1 + 0.9.1 + + + beta + beta + + PHP + +- Compatible with PHP5.3+ +- Fix ZTS build +- Fix mem leak when get value from lua + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.1.0 + 5.4.0 + + + 1.4.0 + + + + lua + + + + 2011-11-24 + + 0.9.1 + 0.9.1 + + + beta + beta + + PHP License + + - Compatible with PHP5.3+ + - Fix ZTS build + - Fix mem leak when get value from lua + + + + 2011-08-03 + + 0.9.0 + 0.9.0 + + + beta + beta + + PHP License + + - Merge Plua into Lua + - Api changes + - Add supporting for LUA_TFUNCTION + + + + + diff --git a/php_lua.h b/php_lua.h new file mode 100644 index 0000000..46662d7 --- /dev/null +++ b/php_lua.h @@ -0,0 +1,78 @@ +/* + +----------------------------------------------------------------------+ + | Lua | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author : Johannes Schlueter | + | Xinchen Hui | + | Marcelo Araujo | + +----------------------------------------------------------------------+ + $Id: php_lua.h 319733 2011-11-24 07:13:56Z laruence $ +*/ + +#ifndef PHP_LUA_H +#define PHP_LUA_H + +extern zend_module_entry lua_module_entry; +#define phpext_lua_ptr &lua_module_entry + +#ifdef PHP_WIN32 +#define PHP_LUA_API __declspec(dllexport) +#else +#define PHP_LUA_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +#ifdef ZTS +#define LUA_G(v) TSRMG(lua_globals_id, zend_lua_globals *, v) +#else +#define LUA_G(v) (lua_globals.v) +#endif + +#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 "0.9.0" +#define Z_LUAVAL_P(obj) ((php_lua_object*)(zend_object_store_get_object(obj TSRMLS_CC)))->L + +struct _php_lua_object { + zend_object obj; + lua_State *L; +}; + +typedef struct _php_lua_object php_lua_object; + +zval * php_lua_get_zval_from_lua(lua_State *L, int index, zval *lua_obj TSRMLS_DC); +int php_lua_send_zval_to_lua(lua_State *L, zval *val TSRMLS_DC); + +PHP_MINIT_FUNCTION(lua); +PHP_MSHUTDOWN_FUNCTION(lua); +PHP_MINFO_FUNCTION(lua); + +PHP_METHOD(lua, __construct); +PHP_METHOD(lua, eval); +PHP_METHOD(lua, require); +#endif /* PHP_LUA_H */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/tests/001.phpt b/tests/001.phpt new file mode 100644 index 0000000..9619a82 --- /dev/null +++ b/tests/001.phpt @@ -0,0 +1,16 @@ +--TEST-- +Basic lua check +--SKIPIF-- + +--FILE-- +assign("b", 12); +$l->eval("print(b)"); +$l->eval('print("\n")'); +$l->eval("print(math.sin(b))"); +$l->eval("invalid code"); +--EXPECTF-- +12 +-0.53657291800043 +Warning: Lua::eval(): lua error: [string "line"]:1: '=' expected near 'code' in %s on line %d diff --git a/tests/002.phpt b/tests/002.phpt new file mode 100644 index 0000000..7d125e1 --- /dev/null +++ b/tests/002.phpt @@ -0,0 +1,19 @@ +--TEST-- +Set and read properties +--SKIPIF-- + +--FILE-- +a = "foobar"; +$l->b = 12; +var_dump($l->b); +var_dump($l->a); + +$l->b = null; +var_dump($l->b); +?> +--EXPECT-- +float(12) +string(6) "foobar" +NULL diff --git a/tests/003.phpt b/tests/003.phpt new file mode 100644 index 0000000..af50e46 --- /dev/null +++ b/tests/003.phpt @@ -0,0 +1,95 @@ +--TEST-- +Call lua functions +--SKIPIF-- + +--FILE-- +eval(<<print("Hello world!\n"); +$l->phptest_no_param(); + +$l->phptest_1_param(); +$l->phptest_1_param("foobar"); + +$l->phptest_2_params(); +$l->phptest_2_params("foo"); +$l->phptest_2_params("foo", "bar"); + +echo "\n"; + +var_dump($l->call(array("math", "sin"), array(3/2*pi()))); +var_dump($l->call(array("math", "cos"), array(pi()))); + +echo "\n"; + +try { +$l->notexisting(2423); +$l->call(array("math", "sin", "function"), array(432, 342)); + +} catch (LuaException $e) { + echo $e->getMessage(); +} + +echo "\n"; + +var_dump($l->type("fobar")); +var_dump($l->multiret()); + +echo "\n"; + +var_dump($l->__call("multiret", array())); + +$l->__call("print"); +$l->__call("print", array("foo")); +?> +--EXPECTF-- +Hello world! +No parameters! +Parameter: `'! +Parameter: `foobar'! +Parameter 1: `', Parameter 2: `'! +Parameter 1: `foo', Parameter 2: `'! +Parameter 1: `foo', Parameter 2: `bar'! + +float(-1) +float(-1) + +invalid lua function 'notexisting' +string(6) "string" +array(3) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" + [2]=> + string(1) "c" +} + +array(3) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" + [2]=> + string(1) "c" +} +foo diff --git a/tests/004.phpt b/tests/004.phpt new file mode 100644 index 0000000..dafcfbb --- /dev/null +++ b/tests/004.phpt @@ -0,0 +1,35 @@ +--TEST-- +Type conversion from lua to PHP +--SKIPIF-- + +--FILE-- +eval(<<{$i}); +} +?> +--EXPECT-- +NULL +bool(false) +float(23) +float(-432) +float(432.432) +float(0) +float(1.43E+25) +string(6) "foobar" +string(0) "" diff --git a/tests/005.phpt b/tests/005.phpt new file mode 100644 index 0000000..5b03c17 --- /dev/null +++ b/tests/005.phpt @@ -0,0 +1,17 @@ +--TEST-- +Lua phpinfo() block +--SKIPIF-- + +--FILE-- +info(); +?> +--EXPECTF-- +lua + +lua support => enabled +lua extension version => %s +lua release => %s +lua copyright => %s +lua authors => %s diff --git a/tests/006.phpt b/tests/006.phpt new file mode 100644 index 0000000..39bbac9 --- /dev/null +++ b/tests/006.phpt @@ -0,0 +1,39 @@ +--TEST-- +Lua::include() +--SKIPIF-- + +--FILE-- + 'print "Hello PHP"', + 'broken' => 'dgdr fdrg erb rxdgre tews< df hxfdxgfc gsdgxvrsgrg.ve4w', + 'return' => 'return "php", "lua", "extension"', +); + +$l = new lua(); + +foreach ($code as $n => $c) { + echo "\nTesting $n\n"; + file_put_contents($filename, $c); + $ret = $l->include($filename); + if ($ret) print_r($ret); + @unlink($filename); +} +?> +--EXPECTF-- + +Testing fine +Hello PHP +Testing broken + +Warning: Lua::include(): lua error: %s '=' expected near 'fdrg' in %s on line %d + +Testing return +Array +( + [0] => php + [1] => lua + [2] => extension +) diff --git a/tests/007.phpt b/tests/007.phpt new file mode 100644 index 0000000..d382dda --- /dev/null +++ b/tests/007.phpt @@ -0,0 +1,30 @@ +--TEST-- +Lua return function +--SKIPIF-- + +--FILE-- +eval(<<closure(); + +$l->call($func); +unset($func); +$func = $l->closure(); + +$l->call($func); +unset($func); +?> +--EXPECTF-- +lualua diff --git a/tests/008.phpt b/tests/008.phpt new file mode 100644 index 0000000..c18ae93 --- /dev/null +++ b/tests/008.phpt @@ -0,0 +1,41 @@ +--TEST-- +register php function to lua +--SKIPIF-- + +--FILE-- +registerCallback("callphp", array("A", "intro")); + +$l->eval(<<registerCallback("callphp2", array(new B, "intro")); + + +$l->registerCallback("echo", "var_dump"); + +$l->eval(<< +--EXPECTF-- +foobarfoo,barstring(5) "maybe" diff --git a/tests/009.phpt b/tests/009.phpt new file mode 100644 index 0000000..8749a99 --- /dev/null +++ b/tests/009.phpt @@ -0,0 +1,45 @@ +--TEST-- +Bug (eval and include compute wrong return value number) +--SKIPIF-- + +--FILE-- +eval(<<closure(); + +$arr = $l->eval(<<call($func); +unset($func); +$func = $l->closure(); + +$l->call($func); +unset($func); +?> +--EXPECTF-- +Array +( + [0] => 2 + [1] => 3 + [2] => 4 + [3] => 5 + [4] => 6 +) +lualua diff --git a/tests/010.phpt b/tests/010.phpt new file mode 100644 index 0000000..b6b95ba --- /dev/null +++ b/tests/010.phpt @@ -0,0 +1,34 @@ +--TEST-- +LuaClosure exception +--SKIPIF-- + +--FILE-- +eval(<<closure(); + +try { + $l->call($func); + if (version_compare(PHP_VERSION, "5.3.0") >= 0) { + $func(); + } else { + $func->invoke(); + } +} catch (LuaException $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +lualua diff --git a/tests/011.phpt b/tests/011.phpt new file mode 100644 index 0000000..6e6723a --- /dev/null +++ b/tests/011.phpt @@ -0,0 +1,18 @@ +--TEST-- +register invalid php callback to lua +--SKIPIF-- + +--FILE-- +registerCallback("callphp", "print"); + echo "okey"; +} catch (Exception $e) { + echo $e->getMessage(); +} + +--EXPECT-- +invalid php callback