cvs: php-gtk / config.m4 /demos/examples properties.php /ext/gtk+ gtk.overrides gtktreeview.overrides php_gtk+_types.c phpg_custom_tree_model.c
/main php_gtk.c php_gtk.h php_gtk_util.c phpg_closure.c phpg_gobject.c phpg_gtype.c phpg_gvalue.c phpg_paramspec.c phpg_support.c

From: Date: Sun, 16 Sep 2007 21:55:19 +0000
Subject: cvs: php-gtk / config.m4 /demos/examples properties.php /ext/gtk+ gtk.overrides gtktreeview.overrides php_gtk+_types.c phpg_custom_tree_model.c
/main php_gtk.c php_gtk.h php_gtk_util.c phpg_closure.c phpg_gobject.c phpg_gtype.c phpg_gvalue.c phpg_paramspec.c phpg_support.c
Groups: php.gtk.cvs 
Request: Send a blank email to php-gtk-cvs+get-2768@lists.php.net to get a copy of this message
andrei Sun Sep 16 21:55:19 2007 UTC Added files: /php-gtk/demos/examples properties.php /php-gtk/main phpg_paramspec.c Modified files: /php-gtk config.m4 /php-gtk/ext/gtk+ gtk.overrides gtktreeview.overrides php_gtk+_types.c phpg_custom_tree_model.c /php-gtk/main php_gtk.c php_gtk.h php_gtk_util.c phpg_closure.c phpg_gobject.c phpg_gtype.c phpg_gvalue.c phpg_support.c Log: First step in the implementation of custom GType's in PHP userland. Signals and interfaces are not implemented yet. See demos/examples/properties.php for an example on how to register a custom type with your own properties.

http://cvs.php.net/viewvc.cgi/php-gtk/config.m4?r1=1.21&r2=1.22&diff_format=u Index: php-gtk/config.m4 diff -u php-gtk/config.m4:1.21 php-gtk/config.m4:1.22 --- php-gtk/config.m4:1.21 Fri Aug 17 22:51:04 2007 +++ php-gtk/config.m4 Sun Sep 16 21:55:18 2007 @@ -1,4 +1,4 @@ -dnl $Id: config.m4,v 1.21 2007/08/17 22:51:04 andrei Exp $ +dnl $Id: config.m4,v 1.22 2007/09/16 21:55:18 andrei Exp $ dnl config.m4 for extension php-gtk PHP_ARG_ENABLE(php-gtk,for PHP-GTK support, @@ -70,7 +70,7 @@ PHP_NEW_EXTENSION(php_gtk2, main/php_gtk.c main/phpg_support.c main/phpg_gtype.c \ main/phpg_exceptions.c main/php_gtk_util.c main/phpg_gvalue.c \ main/phpg_closure.c main/phpg_gboxed.c main/phpg_gpointer.c \ - main/phpg_atom.c main/phpg_gobject.c, + main/phpg_atom.c main/phpg_paramspec.c main/phpg_gobject.c, $ext_shared,, -I@ext_srcdir@/main) PHP_ADD_SOURCES_X(/main, php_gtk_ext.c,, shared_objects_php_gtk2) http://cvs.php.net/viewvc.cgi/php-gtk/ext/gtk+/gtk.overrides?r1=1.247&r2=1.248&diff_format=u Index: php-gtk/ext/gtk+/gtk.overrides diff -u php-gtk/ext/gtk+/gtk.overrides:1.247 php-gtk/ext/gtk+/gtk.overrides:1.248 --- php-gtk/ext/gtk+/gtk.overrides:1.247 Wed Jul 18 17:48:49 2007 +++ php-gtk/ext/gtk+/gtk.overrides Sun Sep 16 21:55:18 2007 @@ -6131,4 +6131,4 @@ %% include gtktextview.overrides %% include gtktreeview.overrides %% include gtk-2.8.overrides 2.8 -%% include gtk-2.10.overrides "2.10" +%% include gtk-2.10.overrides 2.10 http://cvs.php.net/viewvc.cgi/php-gtk/ext/gtk+/gtktreeview.overrides?r1=1.81&r2=1.82&diff_format=u Index: php-gtk/ext/gtk+/gtktreeview.overrides diff -u php-gtk/ext/gtk+/gtktreeview.overrides:1.81 php-gtk/ext/gtk+/gtktreeview.overrides:1.82 --- php-gtk/ext/gtk+/gtktreeview.overrides:1.81 Fri Jun 22 21:33:34 2007 +++ php-gtk/ext/gtk+/gtktreeview.overrides Sun Sep 16 21:55:18 2007 @@ -451,7 +451,7 @@ g_value_init(&values[i], gtk_tree_model_get_column_type(model, i)); - if (phpg_gvalue_from_zval(&values[i], *item, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&values[i], item, TRUE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Cannot set row: type of element %d does not match the model", i); for ( ; i >= 0; i--) { g_value_unset(&values[i]); @@ -516,7 +516,7 @@ g_value_init(&value, gtk_tree_model_get_column_type(model, i)); - if (phpg_gvalue_from_zval(&value, *item, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&value, item, TRUE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Cannot set row: type of element %d does not match the model", i); g_value_unset(&value); return; @@ -567,7 +567,7 @@ g_value_init(&value, gtk_tree_model_get_column_type(model, i)); - if (phpg_gvalue_from_zval(&value, *item, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&value, item, TRUE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Cannot set row: type of element %d does not match the model", i); g_value_unset(&value); return; @@ -647,7 +647,7 @@ g_value_init(&value, gtk_tree_model_get_column_type(model, column)); - if (phpg_gvalue_from_zval(&value, zvalue, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&value, &zvalue, TRUE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "%s::%s(): argument %d is of the wrong type for column %d", get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C), i+1, column); http://cvs.php.net/viewvc.cgi/php-gtk/ext/gtk+/php_gtk+_types.c?r1=1.50&r2=1.51&diff_format=u Index: php-gtk/ext/gtk+/php_gtk+_types.c diff -u php-gtk/ext/gtk+/php_gtk+_types.c:1.50 php-gtk/ext/gtk+/php_gtk+_types.c:1.51 --- php-gtk/ext/gtk+/php_gtk+_types.c:1.50 Sun Oct 8 19:03:47 2006 +++ php-gtk/ext/gtk+/php_gtk+_types.c Sun Sep 16 21:55:18 2007 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: php_gtk+_types.c,v 1.50 2006/10/08 19:03:47 andrei Exp $ */ +/* $Id: php_gtk+_types.c,v 1.51 2007/09/16 21:55:18 andrei Exp $ */ #include "php_gtk.h" @@ -433,7 +433,7 @@ zend_hash_move_forward(Z_ARRVAL_P(items)), i++) { GValue value = { 0, }; g_value_init(&value, gtk_tree_model_get_column_type(model, i)); - if (phpg_gvalue_from_zval(&value, *item, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&value, item, TRUE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Cannot set row: type of element %d does not match the model", i); return FAILURE; } @@ -1015,7 +1015,7 @@ } g_value_init(&gvalue, gtk_tree_model_get_column_type(row->model, column)); - if (phpg_gvalue_from_zval(&gvalue, value, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&gvalue, &value, TRUE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Cannot set cell: the type of value does not match the model column"); return; } http://cvs.php.net/viewvc.cgi/php-gtk/ext/gtk+/phpg_custom_tree_model.c?r1=1.6&r2=1.7&diff_format=u Index: php-gtk/ext/gtk+/phpg_custom_tree_model.c diff -u php-gtk/ext/gtk+/phpg_custom_tree_model.c:1.6 php-gtk/ext/gtk+/phpg_custom_tree_model.c:1.7 --- php-gtk/ext/gtk+/phpg_custom_tree_model.c:1.6 Tue Oct 24 12:46:14 2006 +++ php-gtk/ext/gtk+/phpg_custom_tree_model.c Sun Sep 16 21:55:18 2007 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: phpg_custom_tree_model.c,v 1.6 2006/10/24 12:46:14 sfox Exp $: */ +/* $Id: phpg_custom_tree_model.c,v 1.7 2007/09/16 21:55:18 andrei Exp $: */ #include "php_gtk.h" @@ -377,7 +377,7 @@ if (call_user_function_ex(EG(function_table), &wrapper, &method_name, &retval, 2, args, 0, NULL TSRMLS_CC) == SUCCESS && retval) { if (Z_TYPE_P(retval) != IS_NULL) { - if (phpg_gvalue_from_zval(value, retval, 1 TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(value, &retval, 1 TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Could not convert return value to appropriate type"); } } http://cvs.php.net/viewvc.cgi/php-gtk/main/php_gtk.c?r1=1.56&r2=1.57&diff_format=u Index: php-gtk/main/php_gtk.c diff -u php-gtk/main/php_gtk.c:1.56 php-gtk/main/php_gtk.c:1.57 --- php-gtk/main/php_gtk.c:1.56 Sat Sep 9 17:58:57 2006 +++ php-gtk/main/php_gtk.c Sun Sep 16 21:55:18 2007 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: php_gtk.c,v 1.56 2006/09/09 17:58:57 andrei Exp $: */ +/* $Id: php_gtk.c,v 1.57 2007/09/16 21:55:18 andrei Exp $: */ #include "php_gtk.h" #include "SAPI.h" @@ -182,13 +182,15 @@ * Initialize the type system and the GType wrapper class. */ g_type_init(); + + G_TYPE_PHP_VALUE = g_boxed_type_register_static("PhpValue", php_object_copy, php_object_release); + phpg_gtype_register_self(TSRMLS_C); phpg_gobject_register_self(TSRMLS_C); phpg_gboxed_register_self(TSRMLS_C); phpg_gpointer_register_self(TSRMLS_C); phpg_gdkatom_register_self(TSRMLS_C); - - G_TYPE_PHP_VALUE = g_boxed_type_register_static("PhpValue", php_object_copy, php_object_release); + phpg_paramspec_register_self(TSRMLS_C); if (php_gtk_startup_all_extensions(module_number) == FAILURE) { php_error(E_WARNING, "Unable to start internal extensions"); http://cvs.php.net/viewvc.cgi/php-gtk/main/php_gtk.h?r1=1.147&r2=1.148&diff_format=u Index: php-gtk/main/php_gtk.h diff -u php-gtk/main/php_gtk.h:1.147 php-gtk/main/php_gtk.h:1.148 --- php-gtk/main/php_gtk.h:1.147 Sun Jun 17 00:21:21 2007 +++ php-gtk/main/php_gtk.h Sun Sep 16 21:55:18 2007 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: php_gtk.h,v 1.147 2007/06/17 00:21:21 anant Exp $: */ +/* $Id: php_gtk.h,v 1.148 2007/09/16 21:55:18 andrei Exp $: */ #ifndef _PHP_GTK_H #define _PHP_GTK_H @@ -136,6 +136,12 @@ GdkAtom atom; } phpg_gdkatom_t; +typedef struct { + PHPG_OBJ_HEADER + GParamSpec *pspec; +} phpg_paramspec_t; + + typedef int (*boxed_from_zval_t)(const zval *value, GValue *gvalue TSRMLS_DC); typedef int (*boxed_to_zval_t)(const GValue *gvalue, zval **value TSRMLS_DC); typedef struct { @@ -164,6 +170,8 @@ #define PHPG_GDKATOM(zobj) ((phpg_gdkatom_t*)PHPG_GET(zobj))->atom +#define PHPG_GPARAMSPEC(zobj) phpg_gparamspec_get(zobj TSRMLS_CC)->pspec + /* * Property read/write function types @@ -296,6 +304,7 @@ PHP_GTK_API int php_gtk_parse_varargs(int argc, int min_args, zval **varargs, char *format, ...); PHP_GTK_API int php_gtk_parse_args_hash(zval *hash, char *format, ...); PHP_GTK_API int php_gtk_parse_args_hash_quiet(zval *hash, char *format, ...); +PHP_GTK_API int php_gtk_parse_varargs_hash(zval *hash, int min_args, zval **varargs, char *format, ...); PHP_GTK_API int php_gtk_check_class(zval *wrapper, zend_class_entry *expected_ce); PHP_GTK_API void php_gtk_invalidate(zval *wrapper); zend_bool php_gtk_is_callable(zval *callable, zend_bool syntax_only, char **callable_name); @@ -425,14 +434,14 @@ void phpg_gtype_register_self(TSRMLS_D); PHP_GTK_API void phpg_gtype_new(zval *zobj, GType type TSRMLS_DC); PHP_GTK_API GType phpg_gtype_from_zval(zval *value); -PHP_GTK_API GType phpg_gtype_from_class(zend_class_entry *ce); +PHP_GTK_API GType phpg_gtype_from_class(zend_class_entry *ce TSRMLS_DC); /* GValue */ PHP_GTK_API int phpg_gvalue_to_zval(const GValue *gval, zval **value, zend_bool copy_boxed, zend_bool do_utf8 TSRMLS_DC); -PHP_GTK_API int phpg_gvalue_from_zval(GValue *gval, zval *value, zend_bool do_utf8 TSRMLS_DC); +PHP_GTK_API int phpg_gvalue_from_zval(GValue *gval, zval **value, zend_bool do_utf8 TSRMLS_DC); PHP_GTK_API int phpg_param_gvalue_to_zval(const GValue *gval, zval **value, zend_bool copy_boxed, const GParamSpec *pspec TSRMLS_DC); -PHP_GTK_API int phpg_param_gvalue_from_zval(GValue *gval, zval *value, const GParamSpec *pspec TSRMLS_DC); +PHP_GTK_API int phpg_param_gvalue_from_zval(GValue *gval, zval **value, const GParamSpec *pspec TSRMLS_DC); PHP_GTK_API zval *phpg_gvalues_to_array(const GValue *values, uint n_values); PHP_GTK_API int phpg_gvalue_get_enum(GType enum_type, zval *enum_val, gint *result); PHP_GTK_API int phpg_gvalue_get_flags(GType flags_type, zval *flags_val, gint *result); @@ -494,6 +503,17 @@ PHP_GTK_API void phpg_gdkatom_new(zval **zobj, GdkAtom atom TSRMLS_DC); PHP_GTK_API GdkAtom phpg_gdkatom_from_zval(zval *value TSRMLS_DC); +/* GParamSpec */ +PHP_GTK_API void phpg_paramspec_new(zval **zobj, GParamSpec *pspec TSRMLS_DC); +static inline phpg_paramspec_t* phpg_gparamspec_get(zval *zobj TSRMLS_DC) +{ + phpg_paramspec_t *pobj = zend_object_store_get_object(zobj TSRMLS_CC); + if (pobj->pspec == NULL) { + php_error(E_ERROR, "Internal object missing in %s wrapper", Z_OBJCE_P(zobj)->name); + } + return pobj; +} + /* Closures */ PHP_GTK_API GClosure* phpg_closure_new(zval *callback, zval *user_args, int connect_type, zval *replace_object TSRMLS_DC); PHP_GTK_API void phpg_watch_closure(zval *obj, GClosure *closure TSRMLS_DC); @@ -503,6 +523,7 @@ PHP_GTK_API extern PHP_GTK_EXPORT_CE(gboxed_ce); PHP_GTK_API extern PHP_GTK_EXPORT_CE(gpointer_ce); PHP_GTK_API extern PHP_GTK_EXPORT_CE(gdkatom_ce); +PHP_GTK_API extern PHP_GTK_EXPORT_CE(gparamspec_ce); #endif /* HAVE_PHP_GTK */ http://cvs.php.net/viewvc.cgi/php-gtk/main/php_gtk_util.c?r1=1.62&r2=1.63&diff_format=u Index: php-gtk/main/php_gtk_util.c diff -u php-gtk/main/php_gtk_util.c:1.62 php-gtk/main/php_gtk_util.c:1.63 --- php-gtk/main/php_gtk_util.c:1.62 Sat Jan 20 20:21:30 2007 +++ php-gtk/main/php_gtk_util.c Sun Sep 16 21:55:18 2007 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: php_gtk_util.c,v 1.62 2007/01/20 20:21:30 andrei Exp $ */ +/* $Id: php_gtk_util.c,v 1.63 2007/09/16 21:55:18 andrei Exp $ */ #include "php_gtk.h" @@ -57,7 +57,7 @@ } } -static char *parse_arg_impl(zval **arg, va_list *va, char **spec, char *buf, int as_zval TSRMLS_DC) +static char *parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec, char *buf, int as_zval TSRMLS_DC) { char *spec_walk = *spec; char c = *spec_walk++; @@ -351,6 +351,44 @@ } break; + case 'C': + { + zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **); + zend_class_entry *ce_base = *pce; + + if (return_null && Z_TYPE_PP(arg) == IS_NULL) { + *pce = NULL; + break; + } + convert_to_string_ex(arg); + if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) { + *pce = NULL; + } else { + *pce = *lookup; + } + if (ce_base) { + if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC)) && !return_null) { + char *space; + char *class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", + class_name, space, get_active_function_name(TSRMLS_C), + arg_num, ce_base->name, Z_STRVAL_PP(arg)); + *pce = NULL; + return ""; + } + } + if (!*pce) { + char *space; + char *class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a valid class name, '%s' given", + class_name, space, get_active_function_name(TSRMLS_C), + arg_num, Z_STRVAL_PP(arg)); + return ""; + } + break; + + } + break; case 'V': ret_zval: { @@ -374,9 +412,9 @@ char buf[1024]; char errorbuf[1024]; - expected_type = parse_arg_impl(arg, va, spec, errorbuf, as_zval TSRMLS_CC); + expected_type = parse_arg_impl(arg_num, arg, va, spec, errorbuf, as_zval TSRMLS_CC); if (expected_type) { - if (!quiet) { + if (!quiet && *expected_type) { sprintf(buf, "%s::%s() expects argument %d to be %s, %s given", get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C), arg_num, expected_type, @@ -411,7 +449,7 @@ case 'i': case 'h': case 'l': case 'c': case 's': case 'd': case 'b': case 'u': - case 'a': case 'N': case 'r': + case 'a': case 'N': case 'r': case 'C': case 'O': case 'o': case 'V': max_argc++; break; @@ -571,6 +609,30 @@ return retval; } +static int php_gtk_parse_varargs_hash_impl(zval *hash, int min_args, zval **varargs, char *format, va_list *va, int quiet) +{ + zval ***args; + int retval; + int argc = zend_hash_num_elements(Z_ARRVAL_P(hash)); + TSRMLS_FETCH(); + + if (argc < min_args) { + php_error(E_WARNING, "%s::%s() requires at least %d arguments, %d given", + get_active_class_name(NULL TSRMLS_CC), + get_active_function_name(TSRMLS_C), min_args, argc); + return 0; + } + + args = php_gtk_hash_as_array(hash); + retval = parse_va_args(min_args, args, format, va, quiet TSRMLS_CC); + if (varargs) { + *varargs = php_gtk_array_as_hash(args, argc, min_args, argc-min_args); + } + efree(args); + + return retval; +} + PHP_GTK_API int php_gtk_parse_args_hash(zval *hash, char *format, ...) { va_list va; @@ -595,6 +657,18 @@ return retval; } +PHP_GTK_API int php_gtk_parse_varargs_hash(zval *hash, int min_args, zval **varargs, char *format, ...) +{ + va_list va; + int retval; + + va_start(va, format); + retval = php_gtk_parse_varargs_hash_impl(hash, min_args, varargs, format, &va, 0); + va_end(va); + + return retval; +} + PHP_GTK_API int php_gtk_check_class(zval *wrapper, zend_class_entry *expected_ce) { TSRMLS_FETCH(); http://cvs.php.net/viewvc.cgi/php-gtk/main/phpg_closure.c?r1=1.16&r2=1.17&diff_format=u Index: php-gtk/main/phpg_closure.c diff -u php-gtk/main/phpg_closure.c:1.16 php-gtk/main/phpg_closure.c:1.17 --- php-gtk/main/phpg_closure.c:1.16 Sat Sep 9 17:58:57 2006 +++ php-gtk/main/phpg_closure.c Sun Sep 16 21:55:18 2007 @@ -126,7 +126,7 @@ if (retval) { if (return_value) { - if (phpg_gvalue_from_zval(return_value, retval, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(return_value, &retval, TRUE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Could not convert return value of signal callback '%s' to '%s'", callback_name, g_type_name(G_VALUE_TYPE(return_value))); } http://cvs.php.net/viewvc.cgi/php-gtk/main/phpg_gobject.c?r1=1.61&r2=1.62&diff_format=u Index: php-gtk/main/phpg_gobject.c diff -u php-gtk/main/phpg_gobject.c:1.61 php-gtk/main/phpg_gobject.c:1.62 --- php-gtk/main/phpg_gobject.c:1.61 Wed Jul 18 17:48:52 2007 +++ php-gtk/main/phpg_gobject.c Sun Sep 16 21:55:18 2007 @@ -19,6 +19,7 @@ */ #include "php_gtk.h" +#include "zend_interfaces.h" #if HAVE_PHP_GTK @@ -269,8 +270,7 @@ } if ((klass = g_type_class_ref(object_type)) == NULL) { - PHPG_THROW_EXCEPTION_WITH_RETURN(phpg_construct_exception, - "Could not get a reference to type class", 0); + PHPG_THROW_EXCEPTION_WITH_RETURN(phpg_construct_exception, "Could not get a reference to type class", 0); } if (props) { @@ -299,7 +299,7 @@ } g_value_init(&params[n_params].value, G_PARAM_SPEC_VALUE_TYPE(pspec)); - if (phpg_gvalue_from_zval(&params[n_params].value, *value, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&params[n_params].value, value, TRUE TSRMLS_CC) == FAILURE) { snprintf(buf, 128, "Could not convert value for property '%s'", key); zend_throw_exception(phpg_construct_exception, buf, 0 TSRMLS_CC); goto cleanup; @@ -513,13 +513,13 @@ obj = PHPG_GOBJECT(this_ptr); pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), property); if (pspec == NULL) { - php_error(E_WARNING, "Class '%s' does not support property '%s'", - g_type_name(G_TYPE_FROM_INSTANCE(obj)), property); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "class '%s' does not support property '%s'", + g_type_name(G_TYPE_FROM_INSTANCE(obj)), property); return; } if (!(pspec->flags & G_PARAM_READABLE)) { - php_error(E_WARNING, "Property '%s' is not readable", property); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "property '%s' is not readable", property); return; } @@ -545,20 +545,19 @@ obj = PHPG_GOBJECT(this_ptr); pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), property); if (pspec == NULL) { - php_error(E_WARNING, "Class '%s' does not support property '%s'", - g_type_name(G_TYPE_FROM_INSTANCE(obj)), property); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "class '%s' does not support property '%s'", + g_type_name(G_TYPE_FROM_INSTANCE(obj)), property); return; } if (!(pspec->flags & G_PARAM_WRITABLE)) { - php_error(E_WARNING, "Property '%s' is not writable", property); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "property '%s' is not writable", property); return; } g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec)); - if (phpg_param_gvalue_from_zval(&value, php_value, pspec TSRMLS_CC) == FAILURE) { - php_error(E_WARNING, "%s::%s(): could not convert value to property type", - get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C)); + if (phpg_param_gvalue_from_zval(&value, &php_value, pspec TSRMLS_CC) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert value to property type"); return; } g_object_set_property(obj, property, &value); @@ -680,6 +679,7 @@ } /* }}} */ +/* {{{ GObject::emit */ static PHP_METHOD(GObject, emit) { char *signal; @@ -721,7 +721,7 @@ { g_value_init(&params[i], query.param_types[i-1] & ~G_SIGNAL_TYPE_STATIC_SCOPE); - if (phpg_gvalue_from_zval(&params[i], *item, TRUE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&params[i], item, TRUE TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert value to %s for parameter %d", g_type_name(G_VALUE_TYPE(&params[i])), i-1); @@ -750,6 +750,7 @@ zval_ptr_dtor(&extra); } } +/* }}} */ /* {{{ GObject::signal_list_ids/names */ static void phpg_signal_list_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool list_names) @@ -886,6 +887,447 @@ } /* }}} */ +static PHP_METHOD(GObject, list_properties) +{ + GParamSpec **specs; + guint n_specs; + zval *php_type; + GType type; + GObjectClass *oclass; + guint i; + + if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "V", &php_type)) { + return; + } + + if ((type = phpg_gtype_from_zval(php_type)) == 0) { + return; + } + + if (!g_type_is_a(type, G_TYPE_OBJECT)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "type must be derived from GObject"); + return; + } + + oclass = g_type_class_ref(type); + if (!oclass) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "couuld not get a reference to type class"); + return; + } + + specs = g_object_class_list_properties(oclass, &n_specs); + array_init(return_value); + for (i = 0; i < n_specs; i++) { + zval *item = NULL; + phpg_paramspec_new(&item, specs[i] TSRMLS_CC); + add_next_index_zval(return_value, item); + } + + g_free(specs); + g_type_class_unref(oclass); +} + +/* {{{ GObject::register_type */ + +static void phpg_object_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + zval *php_object = NULL; + zval *php_pspec = NULL; + zval *retval = NULL; + + phpg_gobject_new(&php_object, object TSRMLS_CC); + phpg_paramspec_new(&php_pspec, pspec TSRMLS_CC); + + zend_call_method_with_1_params(&php_object, Z_OBJCE_P(php_object), NULL, "do_get_property", &retval, php_pspec); + SEPARATE_ZVAL(&retval); + + if (retval) { + if (phpg_gvalue_from_zval(value, &retval, TRUE TSRMLS_CC) == FAILURE) { + php_error(E_WARNING, "phpg_object_get_property: could not convert PHP value to GValue"); + } + zval_ptr_dtor(&retval); + } else { + php_error(E_WARNING, "phpg_object_get_property: error invoking do_get_property"); + } + zval_ptr_dtor(&php_object); + zval_ptr_dtor(&php_pspec); +} + +static void phpg_object_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + zval *php_object = NULL; + zval *php_pspec = NULL; + zval *php_value = NULL; + zval *retval = NULL; + + if (phpg_gvalue_to_zval(value, &php_value, TRUE, TRUE TSRMLS_CC) == FAILURE) { + php_error(E_WARNING, "phpg_object_set_property: could not convert GValue to PHP value"); + zval_ptr_dtor(&php_value); + return; + } + + phpg_gobject_new(&php_object, object TSRMLS_CC); + phpg_paramspec_new(&php_pspec, pspec TSRMLS_CC); + + zend_call_method_with_2_params(&php_object, Z_OBJCE_P(php_object), NULL, "do_set_property", &retval, php_pspec, php_value); + + if (retval) { + zval_ptr_dtor(&retval); + } + zval_ptr_dtor(&php_object); + zval_ptr_dtor(&php_pspec); + zval_ptr_dtor(&php_value); +} + +static void phpg_object_class_init(GObjectClass *class, zend_class_entry *ce) +{ + class->get_property = phpg_object_get_property; + class->set_property = phpg_object_set_property; +} + +static GParamSpec* phpg_create_property(const char *prop_name, GType prop_type, const char *nick, const char *blurb, zval *type_args, GParamFlags flags) +{ + GParamSpec *pspec = NULL; + + switch (G_TYPE_FUNDAMENTAL(prop_type)) { + case G_TYPE_CHAR: + { + gchar minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "ccc", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_char(prop_name, nick, blurb, minimum, maximum, default_val, flags); + } + break; + + case G_TYPE_UCHAR: + { + gchar minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "ccc", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_uchar(prop_name, nick, blurb, minimum, maximum, default_val, flags); + } + break; + + case G_TYPE_BOOLEAN: + { + zend_bool default_val; + if (!php_gtk_parse_args_hash(type_args, "b", &default_val)) { + return NULL; + } + pspec = g_param_spec_boolean(prop_name, nick, blurb, (gboolean)default_val, flags); + } + break; + + case G_TYPE_INT: + { + int minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "iii", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_int(prop_name, nick, blurb, (gint)minimum, (gint)maximum, (gint)default_val, flags); + } + break; + + case G_TYPE_UINT: + { + int minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "iii", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_uint(prop_name, nick, blurb, (guint)minimum, (guint)maximum, (guint)default_val, flags); + } + break; + + case G_TYPE_LONG: + { + long minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "lll", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_long(prop_name, nick, blurb, (glong)minimum, (glong)maximum, (glong)default_val, flags); + } + break; + + case G_TYPE_ULONG: + { + long minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "lll", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_ulong(prop_name, nick, blurb, (gulong)minimum, (gulong)maximum, (gulong)default_val, flags); + } + break; + + case G_TYPE_ENUM: + { + long default_val; + if (!php_gtk_parse_args_hash(type_args, "l", &default_val)) { + return NULL; + } + pspec = g_param_spec_enum(prop_name, nick, blurb, prop_type, default_val, flags); + } + break; + + case G_TYPE_FLAGS: + { + long default_val; + if (!php_gtk_parse_args_hash(type_args, "l", &default_val)) { + return NULL; + } + pspec = g_param_spec_flags(prop_name, nick, blurb, prop_type, default_val, flags); + } + break; + + case G_TYPE_FLOAT: + { + double minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "ddd", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_float(prop_name, nick, blurb, (float)minimum, + (float)maximum, (float)default_val, flags); + } + break; + + case G_TYPE_DOUBLE: + { + double minimum, maximum, default_val; + if (!php_gtk_parse_args_hash(type_args, "ddd", &minimum, &maximum, &default_val)) { + return NULL; + } + pspec = g_param_spec_double(prop_name, nick, blurb, minimum, maximum, default_val, flags); + } + break; + + case G_TYPE_STRING: + { + char *default_val; + zend_bool free_default_val = FALSE; + + if (!php_gtk_parse_args_hash(type_args, "u", &default_val, &free_default_val)) { + return NULL; + } + pspec = g_param_spec_string(prop_name, nick, blurb, default_val, flags); + if (free_default_val) g_free(default_val); + } + break; + + case G_TYPE_PARAM: + { + pspec = g_param_spec_param(prop_name, nick, blurb, prop_type, flags); + } + break; + + case G_TYPE_BOXED: + { + pspec = g_param_spec_boxed(prop_name, nick, blurb, prop_type, flags); + } + break; + + case G_TYPE_POINTER: + { + pspec = g_param_spec_pointer(prop_name, nick, blurb, flags); + } + break; + + case G_TYPE_OBJECT: + { + pspec = g_param_spec_object(prop_name, nick, blurb, prop_type, flags); + } + break; + + default: + /* unhandled pspec type */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not create param spec for type '%s'", g_type_name(prop_type)); + return NULL; + + } + + return pspec; +} + +static int phpg_register_properties(GType type, zval *properties) +{ + GObjectClass *oclass; + GParamFlags flags; + GParamSpec *pspec; + GType prop_type; + char *str_key; + const char *nick, *blurb; + int data_len; + int retval = SUCCESS; + uint str_key_len; + ulong num_key; + zval **data; + zval *type_args = NULL; + zval *php_prop_type; + + oclass = g_type_class_ref(type); + if (!oclass) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "couuld not get a reference to type class"); + return FAILURE; + } + + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(properties)); + zend_hash_get_current_data(Z_ARRVAL_P(properties), (void**)&data) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(properties))) { + + if (zend_hash_get_current_key_ex(Z_ARRVAL_P(properties), &str_key, &str_key_len, + &num_key, 0, NULL) != HASH_KEY_IS_STRING) { + continue; + } + + if (Z_TYPE_PP(data) != IS_ARRAY) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "property specs have to be arrays"); + retval = FAILURE; + break; + } + + if ((data_len = zend_hash_num_elements(Z_ARRVAL_PP(data))) < 4) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "property specs must have at least 4 elements"); + retval = FAILURE; + break; + } + + if (!php_gtk_parse_varargs_hash(*data, 4, &type_args, "Vssi", &php_prop_type, &nick, &blurb, &flags)) { + retval = FAILURE; + break; + } + + prop_type = phpg_gtype_from_zval(php_prop_type); + if (prop_type == 0) { + retval = FAILURE; + break; + } + if (type_args == NULL && + (prop_type != G_TYPE_PARAM && + prop_type != G_TYPE_BOXED && + prop_type != G_TYPE_POINTER && + prop_type != G_TYPE_OBJECT)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "property specs require type-specific args"); + retval = FAILURE; + break; + } + + pspec = phpg_create_property(str_key, prop_type, nick, blurb, type_args, flags); + if (pspec) { + g_object_class_install_property(oclass, 1, pspec); + } else { + retval = FAILURE; + break; + } + + if (type_args) { + zval_ptr_dtor(&type_args); + } + } + + if (type_args) { + zval_ptr_dtor(&type_args); + } + g_type_class_unref(oclass); + return retval; +} + +static PHP_METHOD(GObject, register_type) +{ + zend_class_entry *class = gobject_ce; + GType parent_type, new_type; + GTypeQuery query; + const char *type_name; + zval **prop_decls; + + GTypeInfo type_info = { + 0, /* class_size */ + + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + + (GClassInitFunc) phpg_object_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + + 0, /* instance_size */ + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL + }; + + if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "C", &class)) { + return; + } + + parent_type = phpg_gtype_from_class(class); + if (!parent_type) { + return; + } + + type_name = class->name; + if (g_type_from_name(type_name) != 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "type '%s' already exists?", type_name); + return; + } + + type_info.class_data = class; + g_type_query(parent_type, &query); + type_info.class_size = query.class_size; + type_info.instance_size = query.instance_size; + + new_type = g_type_register_static(parent_type, type_name, &type_info, 0); + if (new_type == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not create new GType"); + return; + } + + if (!phpg_class_key) { + phpg_class_key = g_quark_from_static_string(phpg_class_id); + } + + g_type_set_qdata(new_type, phpg_class_key, class); + zend_declare_class_constant_long(class, "gtype", sizeof("gtype")-1, new_type); + + zend_update_class_constants(class TSRMLS_CC); + + /* register properties */ + if (zend_hash_find(&class->default_properties, "__gproperties", sizeof("__gproperties"), (void**)&prop_decls) == SUCCESS) { + if (Z_TYPE_PP(prop_decls) != IS_ARRAY) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "__gproperties variable has to be an array"); + return; + } + if (phpg_register_properties(new_type, *prop_decls TSRMLS_CC) == FAILURE) { + return; + } + zend_hash_del(&class->default_properties, "__gproperties", sizeof("__gproperties")); + } + + /* register signals */ + + /*TODO interface registration */ +#if 0 + if (class->num_interfaces > 0) { + int i; + GType itype; + zend_classs_entry *iface; + const GInterfaceInfo *iinfo; + + for (i = 0; i < class->num_interfaces; i++) { + + /* TODO might have to create GInterface type and check if interface class + * inherits from it + */ + itype = phpg_gtype_from_class(class->interfaces[i]); + /* TODO get interface info */ + } + } +#endif + + /* run class init */ + /* TODO virtual method stuff */ + + RETURN_TRUE; +} +/* }}} */ /* {{{ GObject reflection info */ static @@ -994,10 +1436,20 @@ ZEND_END_ARG_INFO(); static +ZEND_BEGIN_ARG_INFO(arginfo_gobject_list_properties, 0) + ZEND_ARG_INFO(0, gtype) +ZEND_END_ARG_INFO(); + +static ZEND_BEGIN_ARG_INFO(arginfo_gobject_stop_emission, 0) ZEND_ARG_INFO(0, signal) ZEND_END_ARG_INFO(); +static +ZEND_BEGIN_ARG_INFO(arginfo_gobject_register_type, 0) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO(); + /* }}} */ static zend_function_entry gobject_methods[] = { @@ -1023,6 +1475,8 @@ PHP_ME(GObject, is_connected, arginfo_gobject_is_connected , ZEND_ACC_PUBLIC) PHP_ME(GObject, signal_query, arginfo_gobject_signal_query , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(GObject, stop_emission, arginfo_gobject_stop_emission , ZEND_ACC_PUBLIC) + PHP_ME(GObject, register_type, arginfo_gobject_register_type , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(GObject, list_properties, arginfo_gobject_list_properties , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(GObject, signal_list_ids, arginfo_gobject_signal_list_ids , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(GObject, signal_list_names, arginfo_gobject_signal_list_names , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_MALIAS(GObject, emit_stop_by_name, stop_emission, arginfo_gobject_stop_emission, ZEND_ACC_PUBLIC) @@ -1056,7 +1510,7 @@ gobject_ce = phpg_register_class("GObject", gobject_methods, NULL, 0, gobject_props_info, NULL, G_TYPE_OBJECT TSRMLS_CC); phpg_register_int_constant(gobject_ce, "gtype", sizeof("gtype")-1, G_TYPE_OBJECT); - /* Fundamental GTypes */ + /* Fundamental GTypes */ phpg_register_int_constant(gobject_ce, "TYPE_INVALID", sizeof("TYPE_INVALID")-1, G_TYPE_INVALID); phpg_register_int_constant(gobject_ce, "TYPE_NONE", sizeof("TYPE_NONE")-1, G_TYPE_NONE); phpg_register_int_constant(gobject_ce, "TYPE_INTERFACE", sizeof("TYPE_INTERFACE")-1, G_TYPE_INTERFACE); @@ -1088,7 +1542,7 @@ phpg_register_int_constant(gobject_ce, "IO_HUP", sizeof("IO_HUP")-1, G_IO_HUP); phpg_register_int_constant(gobject_ce, "IO_NVAL", sizeof("IO_NVAL")-1, G_IO_NVAL); - /* signal type constants */ + /* Signal type constants */ phpg_register_int_constant(gobject_ce, "SIGNAL_RUN_FIRST", sizeof("SIGNAL_RUN_FIRST")-1, G_SIGNAL_RUN_FIRST); phpg_register_int_constant(gobject_ce, "SIGNAL_RUN_LAST", sizeof("SIGNAL_RUN_LAST")-1, G_SIGNAL_RUN_LAST); phpg_register_int_constant(gobject_ce, "SIGNAL_RUN_CLEANUP", sizeof("SIGNAL_RUN_CLEANUP")-1, G_SIGNAL_RUN_CLEANUP); @@ -1096,6 +1550,14 @@ phpg_register_int_constant(gobject_ce, "SIGNAL_DETAILED", sizeof("SIGNAL_DETAILED")-1, G_SIGNAL_DETAILED); phpg_register_int_constant(gobject_ce, "SIGNAL_ACTION", sizeof("SIGNAL_ACTION")-1, G_SIGNAL_ACTION); phpg_register_int_constant(gobject_ce, "SIGNAL_NO_HOOKS", sizeof("SIGNAL_NO_HOOKS")-1, G_SIGNAL_NO_HOOKS); + + /* Paramspec constants */ + phpg_register_int_constant(gobject_ce, "PARAM_READABLE", sizeof("PARAM_READABLE")-1, G_PARAM_READABLE); + phpg_register_int_constant(gobject_ce, "PARAM_WRITABLE", sizeof("PARAM_WRITABLE")-1, G_PARAM_WRITABLE); + phpg_register_int_constant(gobject_ce, "PARAM_CONSTRUCT", sizeof("PARAM_CONSTRUCT")-1, G_PARAM_CONSTRUCT); + phpg_register_int_constant(gobject_ce, "PARAM_CONSTRUCT_ONLY", sizeof("PARAM_CONSTRUCT_ONLY")-1, G_PARAM_CONSTRUCT_ONLY); + phpg_register_int_constant(gobject_ce, "PARAM_LAX_VALIDATION", sizeof("PARAM_LAX_VALIDATION")-1, G_PARAM_LAX_VALIDATION); + phpg_register_int_constant(gobject_ce, "PARAM_READWRITE", sizeof("PARAM_READWRITE")-1, G_PARAM_READWRITE); } #endif /* HAVE_PHP_GTK */ http://cvs.php.net/viewvc.cgi/php-gtk/main/phpg_gtype.c?r1=1.18&r2=1.19&diff_format=u Index: php-gtk/main/phpg_gtype.c diff -u php-gtk/main/phpg_gtype.c:1.18 php-gtk/main/phpg_gtype.c:1.19 --- php-gtk/main/phpg_gtype.c:1.18 Fri Mar 31 18:10:22 2006 +++ php-gtk/main/phpg_gtype.c Sun Sep 16 21:55:18 2007 @@ -31,6 +31,9 @@ GType type; } phpg_gtype_t; +PHP_GTK_EXPORT_CE(gtype_ce) = NULL; +static zend_object_handlers phpg_gtype_handlers; + static PHP_METHOD(GType, __construct); PHPG_PROP_READER(GType, type); PHPG_PROP_READER(GType, name); @@ -47,8 +50,6 @@ { NULL, NULL, NULL }, }; -PHP_GTK_EXPORT_CE(gtype_ce) = NULL; - static void gtype_free_object_storage(phpg_gtype_t *object TSRMLS_DC) { zend_hash_destroy(object->zobj.properties); @@ -76,6 +77,34 @@ return zov; } +static int phpg_gtype_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC) +{ + phpg_gtype_t *pobj = zend_object_store_get_object(readobj TSRMLS_CC); + + if (type == IS_LONG) { + INIT_PZVAL(writeobj); + ZVAL_LONG(writeobj, pobj->type); + return SUCCESS; + } + + /* + * XXX doesn't work, since ZEND_ECHO opcode calls zend_std_object_cast_to_string() + * which invokes __toString() instead + */ + if (type == IS_STRING) { + char *buf; + int buf_len; + const char *name = g_type_name(pobj->type); + + buf_len = spprintf(&buf, 128, "[GType %s (%lu)]", name ? name : "invalid", pobj->type); + INIT_PZVAL(writeobj); + ZVAL_STRINGL(writeobj, buf, buf_len, 0); + return SUCCESS; + } + + return FAILURE; +} + static PHP_METHOD(GType, __construct) {} PHPG_PROP_READER(GType, type) @@ -202,6 +231,9 @@ { if (gtype_ce) return; + phpg_gtype_handlers = php_gtk_handlers; + phpg_gtype_handlers.cast_object = phpg_gtype_cast_object; + gtype_ce = phpg_register_class("GType", gtype_methods, NULL, 0, gtype_props_info, gtype_create_object, 0 TSRMLS_CC); } http://cvs.php.net/viewvc.cgi/php-gtk/main/phpg_gvalue.c?r1=1.28&r2=1.29&diff_format=u Index: php-gtk/main/phpg_gvalue.c diff -u php-gtk/main/phpg_gvalue.c:1.28 php-gtk/main/phpg_gvalue.c:1.29 --- php-gtk/main/phpg_gvalue.c:1.28 Sat Feb 18 19:42:28 2006 +++ php-gtk/main/phpg_gvalue.c Sun Sep 16 21:55:18 2007 @@ -26,10 +26,6 @@ * GValue related functions */ -/* TODO - * G_TYPE_PARAM - */ - /* {{{ PHP_GTK_API phpg_gvalue_to_zval() */ PHP_GTK_API int phpg_gvalue_to_zval(const GValue *gval, zval **value, zend_bool copy_boxed, zend_bool do_utf8 TSRMLS_DC) @@ -49,6 +45,7 @@ MAKE_ZVAL_IF_NULL(*value); ZVAL_STRINGL(*value, (char *)&val, 1, 1); } + break; case G_TYPE_UCHAR: { @@ -129,6 +126,10 @@ } break; + case G_TYPE_PARAM: + phpg_paramspec_new(value, g_value_get_param(gval) TSRMLS_CC); + break; + case G_TYPE_OBJECT: phpg_gobject_new(value, g_value_get_object(gval) TSRMLS_CC); break; @@ -203,7 +204,7 @@ /* }}} */ /* {{{ PHP_GTK_API phpg_gvalue_from_zval() */ -PHP_GTK_API int phpg_gvalue_from_zval(GValue *gval, zval *value, zend_bool do_utf8 TSRMLS_DC) +PHP_GTK_API int phpg_gvalue_from_zval(GValue *gval, zval **value, zend_bool do_utf8 TSRMLS_DC) { switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(gval))) { /* @@ -215,54 +216,54 @@ break; case G_TYPE_BOOLEAN: - convert_to_boolean(value); - g_value_set_boolean(gval, (gboolean)Z_BVAL_P(value)); + convert_to_boolean_ex(value); + g_value_set_boolean(gval, (gboolean)Z_BVAL_PP(value)); break; case G_TYPE_CHAR: - convert_to_string(value); - g_value_set_char(gval, Z_STRVAL_P(value)[0]); + convert_to_string_ex(value); + g_value_set_char(gval, Z_STRVAL_PP(value)[0]); break; case G_TYPE_UCHAR: - convert_to_string(value); - g_value_set_uchar(gval, (guchar)Z_STRVAL_P(value)[0]); + convert_to_string_ex(value); + g_value_set_uchar(gval, (guchar)Z_STRVAL_PP(value)[0]); break; case G_TYPE_INT: - convert_to_long(value); - g_value_set_int(gval, (gint)Z_LVAL_P(value)); + convert_to_long_ex(value); + g_value_set_int(gval, (gint)Z_LVAL_PP(value)); break; case G_TYPE_UINT: - convert_to_long(value); - g_value_set_uint(gval, (guint)Z_LVAL_P(value)); + convert_to_long_ex(value); + g_value_set_uint(gval, (guint)Z_LVAL_PP(value)); break; case G_TYPE_LONG: - convert_to_long(value); - g_value_set_long(gval, (glong)Z_LVAL_P(value)); + convert_to_long_ex(value); + g_value_set_long(gval, (glong)Z_LVAL_PP(value)); break; case G_TYPE_ULONG: - convert_to_long(value); - g_value_set_ulong(gval, (gulong)Z_LVAL_P(value)); + convert_to_long_ex(value); + g_value_set_ulong(gval, (gulong)Z_LVAL_PP(value)); break; case G_TYPE_FLOAT: - convert_to_double(value); - g_value_set_float(gval, (gfloat)Z_DVAL_P(value)); + convert_to_double_ex(value); + g_value_set_float(gval, (gfloat)Z_DVAL_PP(value)); break; case G_TYPE_DOUBLE: - convert_to_double(value); - g_value_set_double(gval, Z_DVAL_P(value)); + convert_to_double_ex(value); + g_value_set_double(gval, Z_DVAL_PP(value)); break; case G_TYPE_ENUM: { gint val = 0; - if (phpg_gvalue_get_enum(G_VALUE_TYPE(gval), value, &val) == FAILURE) { + if (phpg_gvalue_get_enum(G_VALUE_TYPE(gval), *value, &val) == FAILURE) { return FAILURE; } g_value_set_enum(gval, val); @@ -272,7 +273,7 @@ case G_TYPE_FLAGS: { gint val = 0; - if (phpg_gvalue_get_flags(G_VALUE_TYPE(gval), value, &val) == FAILURE) { + if (phpg_gvalue_get_flags(G_VALUE_TYPE(gval), *value, &val) == FAILURE) { return FAILURE; } g_value_set_flags(gval, val); @@ -286,10 +287,10 @@ zend_bool free_utf8 = 0; gchar *str; - convert_to_string(value); - str = Z_STRVAL_P(value); + convert_to_string_ex(value); + str = Z_STRVAL_PP(value); if (do_utf8) { - utf8 = phpg_to_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value), &utf8_len, &free_utf8 TSRMLS_CC); + utf8 = phpg_to_utf8(Z_STRVAL_PP(value), Z_STRLEN_PP(value), &utf8_len, &free_utf8 TSRMLS_CC); if (utf8) { str = utf8; } else { @@ -304,12 +305,12 @@ } case G_TYPE_POINTER: - if (Z_TYPE_P(value) == IS_NULL) { + if (Z_TYPE_PP(value) == IS_NULL) { g_value_set_pointer(gval, NULL); - } else if (Z_TYPE_P(value) == IS_OBJECT - && instanceof_function(Z_OBJCE_P(value), gpointer_ce TSRMLS_CC) - && G_VALUE_HOLDS(gval, ((phpg_gpointer_t*)PHPG_GET(value))->gtype)) { - g_value_set_pointer(gval, ((phpg_gpointer_t*)PHPG_GET(value))->pointer); + } else if (Z_TYPE_PP(value) == IS_OBJECT + && instanceof_function(Z_OBJCE_PP(value), gpointer_ce TSRMLS_CC) + && G_VALUE_HOLDS(gval, ((phpg_gpointer_t*)PHPG_GET(*value))->gtype)) { + g_value_set_pointer(gval, ((phpg_gpointer_t*)PHPG_GET(*value))->pointer); } else { return FAILURE; } @@ -319,41 +320,49 @@ { phpg_gboxed_marshal_t *gbm; - if (Z_TYPE_P(value) == IS_NULL) { + if (Z_TYPE_PP(value) == IS_NULL) { g_value_set_boxed(gval, NULL); /* * We should be safe just setting the zval here, since G_TYPE_PHP_VALUE is * supposed to take any zval type. */ } else if (G_VALUE_HOLDS(gval, G_TYPE_PHP_VALUE)) { - g_value_set_boxed(gval, value); - } else if (Z_TYPE_P(value) == IS_OBJECT - && instanceof_function(Z_OBJCE_P(value), gboxed_ce TSRMLS_CC) - && G_VALUE_HOLDS(gval, ((phpg_gboxed_t*)PHPG_GET(value))->gtype)) { - g_value_set_boxed(gval, PHPG_GBOXED(value)); + g_value_set_boxed(gval, *value); + } else if (Z_TYPE_PP(value) == IS_OBJECT + && instanceof_function(Z_OBJCE_PP(value), gboxed_ce TSRMLS_CC) + && G_VALUE_HOLDS(gval, ((phpg_gboxed_t*)PHPG_GET(*value))->gtype)) { + g_value_set_boxed(gval, PHPG_GBOXED(*value)); } else if ((gbm = phpg_gboxed_lookup_custom(G_VALUE_TYPE(gval)))) { - return gbm->from_zval(value, gval TSRMLS_CC); + return gbm->from_zval(*value, gval TSRMLS_CC); } else return FAILURE; break; } + case G_TYPE_PARAM: + if (php_gtk_check_class(*value, gparamspec_ce)) { + g_value_set_param(gval, PHPG_GPARAMSPEC(*value)); + } else { + return FAILURE; + } + break; + case G_TYPE_OBJECT: - if (Z_TYPE_P(value) == IS_NULL) { + if (Z_TYPE_PP(value) == IS_NULL) { g_value_set_object(gval, NULL); - } else if (Z_TYPE_P(value) == IS_OBJECT - && instanceof_function(Z_OBJCE_P(value), gobject_ce TSRMLS_CC) - && G_TYPE_CHECK_INSTANCE_TYPE(PHPG_GOBJECT(value), G_VALUE_TYPE(gval))) { - g_value_set_object(gval, PHPG_GOBJECT(value)); + } else if (Z_TYPE_P(*value) == IS_OBJECT + && instanceof_function(Z_OBJCE_PP(value), gobject_ce TSRMLS_CC) + && G_TYPE_CHECK_INSTANCE_TYPE(PHPG_GOBJECT(*value), G_VALUE_TYPE(gval))) { + g_value_set_object(gval, PHPG_GOBJECT(*value)); } else return FAILURE; break; case G_TYPE_INTERFACE: if (g_type_is_a(G_VALUE_TYPE(gval), G_TYPE_OBJECT) && - Z_TYPE_P(value) == IS_OBJECT && - G_TYPE_CHECK_INSTANCE_TYPE(PHPG_GOBJECT(value), G_VALUE_TYPE(gval))) { - g_value_set_object(gval, PHPG_GOBJECT(value)); + Z_TYPE_PP(value) == IS_OBJECT && + G_TYPE_CHECK_INSTANCE_TYPE(PHPG_GOBJECT(*value), G_VALUE_TYPE(gval))) { + g_value_set_object(gval, PHPG_GOBJECT(*value)); } else { php_error(E_WARNING, "Could not access interface %s", g_type_name(G_VALUE_TYPE(gval))); return FAILURE; @@ -383,7 +392,7 @@ /* }}} */ /* {{{ PHP_GTK_API phpg_param_gvalue_from_zval() */ -PHP_GTK_API int phpg_param_gvalue_from_zval(GValue *gval, zval *value, const GParamSpec *pspec TSRMLS_DC) +PHP_GTK_API int phpg_param_gvalue_from_zval(GValue *gval, zval **value, const GParamSpec *pspec TSRMLS_DC) { if (G_IS_PARAM_SPEC_UNICHAR(pspec)) { /* TODO */ http://cvs.php.net/viewvc.cgi/php-gtk/main/phpg_support.c?r1=1.17&r2=1.18&diff_format=u Index: php-gtk/main/phpg_support.c diff -u php-gtk/main/phpg_support.c:1.17 php-gtk/main/phpg_support.c:1.18 --- php-gtk/main/phpg_support.c:1.17 Sat Mar 3 19:23:02 2007 +++ php-gtk/main/phpg_support.c Sun Sep 16 21:55:18 2007 @@ -345,6 +345,10 @@ { zend_class_entry ce, *real_ce; + if (!phpg_class_key) { + phpg_class_key = g_quark_from_static_string(phpg_class_id); + } + memset(&ce, 0, sizeof(ce)); ce.name = strdup(iface_name); ce.name_length = strlen(iface_name); @@ -600,7 +604,7 @@ params[i].name = prop_names[i]; g_value_init(&params[i].value, spec->value_type); - if (phpg_gvalue_from_zval(&params[i].value, php_args[i], FALSE TSRMLS_CC) == FAILURE) { + if (phpg_gvalue_from_zval(&params[i].value, &php_args[i], FALSE TSRMLS_CC) == FAILURE) { php_error(E_WARNING, "Could not convert value for parameter '%s' of type '%s'", prop_names[i], g_type_name(spec->value_type)); g_type_class_unref(klass); http://cvs.php.net/viewvc.cgi/php-gtk/demos/examples/properties.php?view=markup&rev=1.1 Index: php-gtk/demos/examples/properties.php +++ php-gtk/demos/examples/properties.php <?php class NewType extends GtkLabel { public $__gproperties = array( 'foo' => array(GObject::TYPE_STRING, 'foo property', 'new foo property', GObject::PARAM_READWRITE, 'default foo value'), 'bar' => array(GObject::TYPE_OBJECT, 'bar property', 'new bar property', GObject::PARAM_READWRITE), 'zoo' => array(GObject::TYPE_BOOLEAN, 'zoo property', 'new zoo property', GObject::PARAM_READABLE, 0), ); private $foo; private $bar; private $zoo = 1; function __construct() { parent::__construct(); $this->foo = 'abcdef'; } function do_get_property($spec) { echo "do_get_property called for $spec\n"; if ($spec->name == 'foo') { return $this->foo; } else if ($spec->name == 'bar') { return $this->bar; } else if ($spec->name == 'zoo') { return $this->zoo; } else { trigger_error('Unknown property'); } } function do_set_property($spec, $value) { echo "do_set_property called for $spec = $value\n"; if ($spec->name == 'foo') { $this->foo = $value; } else if ($spec->name == 'bar') { $this->bar = $value; } else { trigger_error('Unknown property'); } } } GObject::register_type('NewType'); echo $c, "\n"; //var_dump(GObject::list_properties('NewType')); $c = new NewType; var_dump($c->get_property('foo')); var_dump($c->get_property('bar')); var_dump($c->get_property('zoo')); //var_dump($c->get_property('unknown')); issues a warning $c->set_property('bar', new GtkButton()); //$c->set_property('zoo', 0); issues a warning echo $c->get_property('bar'); echo "\n"; http://cvs.php.net/viewvc.cgi/php-gtk/main/phpg_paramspec.c?view=markup&rev=1.1 Index: php-gtk/main/phpg_paramspec.c +++ php-gtk/main/phpg_paramspec.c /* * PHP-GTK - The PHP language bindings for GTK+ * * Copyright (C) 2001-2004 Andrei Zmievski <andrei@php.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "php_gtk.h" #if HAVE_PHP_GTK /* * GParamSpec PHP class definition */ PHP_GTK_EXPORT_CE(gparamspec_ce) = NULL; static void phpg_paramspec_free_object_storage(phpg_paramspec_t *object TSRMLS_DC) { zend_hash_destroy(object->zobj.properties); FREE_HASHTABLE(object->zobj.properties); if (object->zobj.guards) { zend_hash_destroy(object->zobj.guards); FREE_HASHTABLE(object->zobj.guards); } if (object->pspec) { g_param_spec_unref(object->pspec); } efree(object); } /* {{{ PHP_GTK_API phpg_create_paramspec() */ PHP_GTK_API zend_object_value phpg_create_paramspec(zend_class_entry *ce TSRMLS_DC) { zend_object_value zov; phpg_paramspec_t *object; object = emalloc(sizeof(phpg_paramspec_t)); phpg_init_object(object, ce); object->pspec = NULL; zov.handlers = &php_gtk_handlers; zov.handle = zend_objects_store_put(object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) phpg_paramspec_free_object_storage, NULL TSRMLS_CC); return zov; } /* }}} */ /* {{{ PHP_GTK_API phpg_paramspec_new() */ PHP_GTK_API void phpg_paramspec_new(zval **zobj, GParamSpec *pspec TSRMLS_DC) { phpg_paramspec_t *pobj = NULL; assert(zobj != NULL); if (*zobj == NULL) { MAKE_STD_ZVAL(*zobj); } ZVAL_NULL(*zobj); if (pspec == NULL) { return; } object_init_ex(*zobj, gparamspec_ce); pobj = zend_object_store_get_object(*zobj TSRMLS_CC); pobj->pspec = g_param_spec_ref(pspec); } /* }}} */ static PHP_METHOD(GParamSpec, __construct) {} /* {{{ GParamSpec::__tostring() */ static PHP_METHOD(GParamSpec, __tostring) { char buf[256]; GParamSpec *pspec = NULL; int numc = 0; NOT_STATIC_METHOD(); pspec = PHPG_GPARAMSPEC(this_ptr); numc = snprintf(buf, sizeof(buf), "[%s '%s']", G_PARAM_SPEC_TYPE_NAME(pspec), g_param_spec_get_name(pspec)); RETURN_STRINGL(buf, numc, 1); } /* }}} */ /* {{{ GParamSpec properties */ PHPG_PROP_READER(GParamSpec, gtype) { phpg_gtype_new(return_value, G_PARAM_SPEC_TYPE(((phpg_paramspec_t *)object)->pspec)); return SUCCESS; } PHPG_PROP_READER(GParamSpec, name) { const char *name = g_param_spec_get_name(((phpg_paramspec_t *)object)->pspec); if (name) { ZVAL_STRING(return_value, (char*)name, 1); } else { ZVAL_NULL(return_value); } return SUCCESS; } PHPG_PROP_READER(GParamSpec, nick) { const char *nick = g_param_spec_get_nick(((phpg_paramspec_t *)object)->pspec); if (nick) { ZVAL_STRING(return_value, (char*)nick, 1); } else { ZVAL_NULL(return_value); } return SUCCESS; } PHPG_PROP_READER(GParamSpec, blurb) { const char *blurb = g_param_spec_get_blurb(((phpg_paramspec_t *)object)->pspec); if (blurb) { ZVAL_STRING(return_value, (char*)blurb, 1); } else { ZVAL_NULL(return_value); } return SUCCESS; } PHPG_PROP_READER(GParamSpec, flags) { ZVAL_LONG(return_value, ((phpg_paramspec_t *)object)->pspec->flags); return SUCCESS; } PHPG_PROP_READER(GParamSpec, owner_type) { phpg_gtype_new(return_value, ((phpg_paramspec_t *)object)->pspec->owner_type); return SUCCESS; } PHPG_PROP_READER(GParamSpec, value_type) { phpg_gtype_new(return_value, ((phpg_paramspec_t *)object)->pspec->value_type); return SUCCESS; } PHPG_PROP_READER(GParamSpec, default_value) { GParamSpec *pspec = ((phpg_paramspec_t *)object)->pspec; ZVAL_NULL(return_value); if (G_IS_PARAM_SPEC_CHAR(pspec)) { char buf[2]; snprintf(buf, 2, "%c", G_PARAM_SPEC_CHAR(pspec)->default_value); ZVAL_STRINGL(return_value, buf, 1, 1); } else if (G_IS_PARAM_SPEC_UCHAR(pspec)) { char buf[2]; snprintf(buf, 2, "%c", G_PARAM_SPEC_UCHAR(pspec)->default_value); ZVAL_STRINGL(return_value, buf, 1, 1); } else if (G_IS_PARAM_SPEC_BOOLEAN(pspec)) { ZVAL_BOOL(return_value, G_PARAM_SPEC_BOOLEAN(pspec)->default_value); } else if (G_IS_PARAM_SPEC_INT(pspec)) { ZVAL_LONG(return_value, G_PARAM_SPEC_INT(pspec)->default_value); } else if (G_IS_PARAM_SPEC_UINT(pspec)) { ZVAL_LONG(return_value, G_PARAM_SPEC_UINT(pspec)->default_value); } else if (G_IS_PARAM_SPEC_LONG(pspec)) { ZVAL_LONG(return_value, G_PARAM_SPEC_LONG(pspec)->default_value); } else if (G_IS_PARAM_SPEC_ULONG(pspec)) { ZVAL_LONG(return_value, G_PARAM_SPEC_ULONG(pspec)->default_value); } else if (G_IS_PARAM_SPEC_UNICHAR(pspec)) { char buf[2]; snprintf(buf, 2, "%c", G_PARAM_SPEC_UCHAR(pspec)->default_value); ZVAL_STRINGL(return_value, buf, 1, 1); } else if (G_IS_PARAM_SPEC_ENUM(pspec)) { ZVAL_LONG(return_value, G_PARAM_SPEC_ENUM(pspec)->default_value); } else if (G_IS_PARAM_SPEC_FLAGS(pspec)) { ZVAL_LONG(return_value, G_PARAM_SPEC_FLAGS(pspec)->default_value); } else if (G_IS_PARAM_SPEC_FLOAT(pspec)) { ZVAL_DOUBLE(return_value, G_PARAM_SPEC_FLOAT(pspec)->default_value); } else if (G_IS_PARAM_SPEC_DOUBLE(pspec)) { ZVAL_DOUBLE(return_value, G_PARAM_SPEC_DOUBLE(pspec)->default_value); } else if (G_IS_PARAM_SPEC_STRING(pspec)) { if (G_PARAM_SPEC_STRING(pspec)->default_value) { ZVAL_STRING(return_value, G_PARAM_SPEC_STRING(pspec)->default_value, 1); } } return SUCCESS; } /* }}} */ static zend_function_entry gparamspec_methods[] = { PHP_ME(GParamSpec, __construct, NULL, ZEND_ACC_PRIVATE) PHP_ME(GParamSpec, __tostring, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; static prop_info_t gparamspec_props_info[] = { { "gtype", PHPG_PROP_READ_FN(GParamSpec, gtype), NULL }, { "name", PHPG_PROP_READ_FN(GParamSpec, name), NULL }, { "nick", PHPG_PROP_READ_FN(GParamSpec, nick), NULL }, { "blurb", PHPG_PROP_READ_FN(GParamSpec, blurb), NULL }, { "flags", PHPG_PROP_READ_FN(GParamSpec, flags), NULL }, { "owner_type", PHPG_PROP_READ_FN(GParamSpec, owner_type), NULL }, { "value_type", PHPG_PROP_READ_FN(GParamSpec, value_type), NULL }, { "default_value", PHPG_PROP_READ_FN(GParamSpec, default_value), NULL }, { NULL, NULL, NULL }, }; void phpg_paramspec_register_self(TSRMLS_D) { if (gparamspec_ce) return; gparamspec_ce = phpg_register_class("GParamSpec", gparamspec_methods, NULL, 0, gparamspec_props_info, phpg_create_paramspec, G_TYPE_PARAM TSRMLS_CC); } #endif /* HAVE_PHP_GTK */ /* vim: set fdm=marker et sts=4: */
« previous php.gtk.cvs (#2768) next »