Skip to content

Instantly share code, notes, and snippets.

@wudi
Created August 14, 2018 10:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wudi/e048c80c46ae0c17a31e5bbdc4197ed5 to your computer and use it in GitHub Desktop.
Save wudi/e048c80c46ae0c17a31e5bbdc4197ed5 to your computer and use it in GitHub Desktop.
closure in extension include USE
/* laravel extension for PHP */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_laravel.h"
#include "zend.h"
#include "zend_API.h"
#include "zend_exceptions.h"
#include "zend_operators.h"
#include "zend_constants.h"
#include "zend_ini.h"
#include "zend_interfaces.h"
#include "zend_closures.h"
#include "zend_generators.h"
#include "zend_extensions.h"
#include "zend_builtin_functions.h"
#include "zend_smart_str.h"
zend_class_entry testobject_ce;
ZEND_BEGIN_ARG_INFO(arginfo_testobject_http_error, 0)
ZEND_END_ARG_INFO()
static const zend_arg_info arginfo_foo1[] = {
ZEND_ARG_CALLABLE_INFO(0, handler, 0)
};
void foo2(INTERNAL_FUNCTION_PARAMETERS)
{
zval *request;
zend_array *options;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "za", &request, &options)) {
RETURN_FALSE;
}
zval *handler = NULL;
zend_string *handler_key = zend_string_init("handler", sizeof("handler") - 1, 0);
handler = zend_hash_find(EX(func)->op_array.static_variables, handler_key);
if(!handler){
zend_string_release(handler_key);
php_error_docref(NULL, E_WARNING, "variable '$handler' is undefined");
RETURN_FALSE;
}
zend_string_release(handler_key);
if (! zend_is_callable(handler, 0, NULL) ) {
zend_string *cbname = zend_get_callable_name(handler);
php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
zend_string_release(cbname);
RETURN_FALSE;
}
zend_fcall_info_init(handler, 0, &fci, &fcc, NULL, NULL);
zend_fcall_info_argn(&fci, 2, request, options);
fci.retval = return_value;
fcc.calling_scope = &testobject_ce;
zend_call_function(&fci, &fcc);
}
static const zend_arg_info arginfo_foo2[] = {
ZEND_ARG_INFO(0, request)
ZEND_ARG_ARRAY_INFO(0, options, 1)
};
void foo1(INTERNAL_FUNCTION_PARAMETERS)
{
zval *handler = NULL;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "z", &handler)) {
RETURN_FALSE;
}
if (! zend_is_callable(handler, 0, NULL) ) {
zend_string *cbname = zend_get_callable_name(handler);
php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
zend_string_release(cbname);
RETURN_FALSE;
}
zend_function func = {0};
zend_string *func_name = zend_string_init("callback", sizeof("callback")-1, 0);
func.type = ZEND_INTERNAL_FUNCTION;
func.common.function_name = func_name;
func.common.fn_flags = ZEND_ACC_CLOSURE;
func.common.num_args = 2;
func.common.required_num_args = 2;
func.common.scope = &testobject_ce;
func.common.arg_info = &arginfo_foo2;
func.internal_function.type = ZEND_INTERNAL_FUNCTION;
func.internal_function.scope = &testobject_ce;
func.internal_function.fn_flags = ZEND_ACC_CLOSURE;
func.internal_function.handler = &foo2;
func.internal_function.module = &laravel_module_entry;
func.internal_function.num_args = 2;
func.internal_function.required_num_args = 2;
func.internal_function.arg_info = &arginfo_foo2;
zend_string_release(func_name);
func.op_array.static_variables = zend_new_array(1);
zend_string *var_name = zend_string_init("handler", sizeof("handler")-1, 0);
zend_hash_update(func.op_array.static_variables, var_name, handler);
zend_string_release(var_name);
zend_create_closure(return_value, &func, &testobject_ce, NULL, getThis());
}
static PHP_METHOD(TestObject, httpError)
{
zend_function func = {0};
zend_string *name = zend_string_init("callback", sizeof("callback")-1, 0);
func.type = ZEND_INTERNAL_FUNCTION;
func.common.function_name = name;
func.common.fn_flags = ZEND_ACC_CLOSURE;
func.common.num_args = 1;
func.common.required_num_args = 1;
func.common.arg_info = &arginfo_foo1;
func.internal_function.type = ZEND_INTERNAL_FUNCTION;
func.internal_function.scope = NULL;
func.internal_function.fn_flags = ZEND_ACC_CLOSURE;
func.internal_function.handler = &foo1;
func.internal_function.module = &laravel_module_entry;
func.internal_function.num_args = 1;
func.internal_function.required_num_args = 1;
func.internal_function.arg_info = &arginfo_foo1;
zend_string_release(name);
zend_create_closure(return_value, &func, &testobject_ce, NULL, getThis());
}
const zend_function_entry testobject_functions[] = {
PHP_ME(TestObject, httpError, arginfo_testobject_http_error, ZEND_ACC_PUBLIC)
PHP_FE_END
};
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(laravel)
{
INIT_CLASS_ENTRY(testobject_ce, "TestObject", testobject_functions);
zend_register_internal_class(&testobject_ce);
return SUCCESS;
}
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(laravel)
{
#if defined(ZTS) && defined(COMPILE_DL_LARAVEL)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(laravel)
{
php_info_print_table_start();
php_info_print_table_header(2, "laravel support", "enabled");
php_info_print_table_end();
}
/* }}} */
/* {{{ laravel_functions[]
*/
static const zend_function_entry laravel_functions[] = {
PHP_FE_END
};
/* }}} */
/* {{{ laravel_module_entry
*/
zend_module_entry laravel_module_entry = {
STANDARD_MODULE_HEADER,
"laravel", /* Extension name */
laravel_functions, /* zend_function_entry */
PHP_MINIT(laravel), /* PHP_MINIT - Module initialization */
NULL, /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(laravel), /* PHP_RINIT - Request initialization */
NULL, /* PHP_RSHUTDOWN - Request shutdown */
PHP_MINFO(laravel), /* PHP_MINFO - Module info */
PHP_LARAVEL_VERSION, /* Version */
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_LARAVEL
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
# endif
ZEND_GET_MODULE(laravel)
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment