From d9238bdd5361c4cf837f86e88ad4fd396f562301 Mon Sep 17 00:00:00 2001 From: Harald Lapp Date: Mon, 26 Aug 2013 15:26:43 +0200 Subject: [PATCH 1/3] moved code inside of source file to prevent compilation error on later commit --- lua.c | 106 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/lua.c b/lua.c index 79b48e4..dd145a6 100644 --- a/lua.c +++ b/lua.c @@ -316,6 +316,59 @@ static void php_lua_write_property(zval *object, zval *member, zval *value, cons } /* }}} */ +/** {{{ 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; + TSRMLS_FETCH(); + + order = lua_tonumber(L, lua_upvalueindex(1)); + + 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 Date: Mon, 26 Aug 2013 15:28:16 +0200 Subject: [PATCH 2/3] added support for callable functions and closures as values returned / injected into lua engine --- lua.c | 88 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/lua.c b/lua.c index dd145a6..b34b1fd 100644 --- a/lua.c +++ b/lua.c @@ -480,48 +480,64 @@ int php_lua_send_zval_to_lua(lua_State *L, zval *val TSRMLS_DC) { case IS_OBJECT: case IS_ARRAY: { - HashTable *ht = NULL; - zval **ppzval = NULL; + if (zend_is_callable(val, 0, NULL TSRMLS_CC)) { + zval* callbacks = NULL; - ht = HASH_OF(val); + callbacks = zend_read_static_property(lua_ce, ZEND_STRL("_callbacks"), 1 TSRMLS_CC); - 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_STRICT, - "attempt to pass an array index begin with 0 to lua"); - } - MAKE_STD_ZVAL(zkey); - ZVAL_LONG(zkey, idx); - break; + if (ZVAL_IS_NULL(callbacks)) { + array_init(callbacks); } - php_lua_send_zval_to_lua(L, zkey TSRMLS_CC); - php_lua_send_zval_to_lua(L, *ppzval TSRMLS_CC); - lua_settable(L, -3); + lua_pushnumber(L, zend_hash_num_elements(Z_ARRVAL_P(callbacks))); + lua_pushcclosure(L, php_lua_call_callback, 1); - zval_ptr_dtor(&zkey); + zval_add_ref(&val); + add_next_index_zval(callbacks, val); + } else { + 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_STRICT, + "attempt to pass an array index begin with 0 to lua"); + } + 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); + } + --ht->nApplyCount; } - --ht->nApplyCount; } break; default: From 96ad976776b30ebee4b623e50c0228541a8f9d5d Mon Sep 17 00:00:00 2001 From: Harald Lapp Date: Mon, 26 Aug 2013 15:40:25 +0200 Subject: [PATCH 3/3] added test for "php closures from lua" functionality --- tests/013.phpt | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/013.phpt diff --git a/tests/013.phpt b/tests/013.phpt new file mode 100644 index 0000000..5da0ed4 --- /dev/null +++ b/tests/013.phpt @@ -0,0 +1,30 @@ +--TEST-- +PHP Closures from Lua +--SKIPIF-- + +--FILE-- +eval(<<test(function($msg) { + print "$msg"; + + return function($msg) { + print "$msg"; + }; + }); +} catch(LuaException $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +called from luareturned from php