Changeset 10985

Show
Ignore:
Timestamp:
06/16/07 12:14:58 (2 years ago)
Author:
piotras
Message:

Added connect "method".
Implemented g_closure for user's callbacks

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/midgard/apis/php4/midgard.c

    r10954 r10985  
    179179 
    180180/* Midgard object methods */ 
    181 #define _MOM 23 
     181#define _MOM 24 
    182182 
    183183static struct  
     
    209209    {"undelete",                ZEND_FN(_php_midgard_object_undelete)                   },  
    210210    {"export",                  ZEND_FN(_php_midgard_object_export)                     }, 
     211    {"connect",                 ZEND_FN(_php_midgard_object_connect)                    }, 
    211212        { NULL, NULL }  
    212213}; 
     
    880881        } 
    881882} 
     883 
     884PHP_FUNCTION(_php_midgard_object_connect) 
     885{ 
     886        CHECK_MGD; 
     887        NOT_STATIC_METHOD(); 
     888        zval *zval_object = getThis(); 
     889 
     890        php_midgard_gobject_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU); 
     891} 
     892 
    882893 
    883894/* End MIDGARD2 methods */ 
  • trunk/midgard/apis/php4/php_midgard_gobject.h

    r10950 r10985  
    4343zend_class_entry *php_midgard_get_baseclass_ptr(zend_class_entry *ce); 
    4444 
     45/* SIGNALS */ 
     46void php_midgard_gobject_connect(INTERNAL_FUNCTION_PARAMETERS); 
     47 
    4548#endif /* PHP_MIDGARD_GOBJECT_GENERIC  */ 
  • trunk/midgard/apis/php4/php_midgard_gobject_generic.c

    r10952 r10985  
    630630        return rce; 
    631631} 
     632 
     633/* SIGNALS */ 
     634 
     635typedef struct { 
     636        GClosure closure; 
     637        zval *callback; 
     638        zval ***args; 
     639        guint argc; 
     640        guint type; 
     641        zval *zobject; 
     642} php_mgd_closure; 
     643 
     644static void php_midgard_closure_invalidate(gpointer data, GClosure *closure) 
     645{ 
     646        php_mgd_closure *mgdclosure = (php_mgd_closure *) closure; 
     647        efree(mgdclosure->args); 
     648 
     649        mgdclosure->callback = NULL; 
     650        mgdclosure->args = NULL; 
     651        mgdclosure->zobject = NULL; 
     652} 
     653 
     654static void php_midgard_closure_marshal(GClosure *closure, 
     655                GValue *return_value, guint n_param_values, 
     656                const GValue *param_values, gpointer invocation_hint, 
     657                gpointer marshal_data) 
     658{ 
     659        php_mgd_closure *mgdclosure = (php_mgd_closure *) closure; 
     660        gchar *callback_func; 
     661 
     662        /* check if method can be invoked for object */ 
     663        if(mgdclosure->zobject != NULL) { 
     664 
     665                gchar *lname =  
     666                        zend_str_tolower_dup(Z_STRVAL_P(mgdclosure->callback),  
     667                                        Z_STRLEN_P(mgdclosure->callback)); 
     668 
     669                if (!zend_hash_exists(&Z_OBJCE_P(mgdclosure->zobject)->function_table,  
     670                                        lname,  
     671                                        Z_STRLEN_P(mgdclosure->callback)+1)) { 
     672                         
     673                        efree(lname); 
     674                        php_error(E_WARNING, "Can not invoke '%s::%s' as callback",  
     675                                        Z_OBJCE_P(mgdclosure->zobject)->name,  
     676                                        Z_STRVAL_P(mgdclosure->callback)); 
     677                        return; 
     678                } 
     679 
     680                efree(lname); 
     681 
     682        } else { 
     683                 
     684                if (!zend_is_callable(mgdclosure->callback, 0, &callback_func)) { 
     685                         
     686                        php_error(E_WARNING, "Can not invoke '%s' callback", callback_func); 
     687                        return; 
     688                } 
     689        } 
     690 
     691        zval *retval = NULL; 
     692        guint i; 
     693        zval ***args = mgdclosure->args; 
     694        guint argc = mgdclosure->argc; 
     695 
     696        if(args != NULL) { 
     697                 
     698                for(i = 0; i < argc ; i++) {                     
     699                        if(*args[i] == NULL){ 
     700                                g_warning("Value is NULL, Setting 0."); 
     701                                MAKE_STD_ZVAL(*args[i]); 
     702                                ZVAL_LONG(*args[i], 0); 
     703                        } 
     704                } 
     705        } 
     706 
     707        if(mgdclosure->zobject != NULL) { 
     708 
     709                call_user_function_ex(NULL, &mgdclosure->zobject , mgdclosure->callback, 
     710                                &retval, argc, args, 0, NULL TSRMLS_CC); 
     711                 
     712        } else { 
     713                 
     714                call_user_function_ex(EG(function_table), NULL, mgdclosure->callback, 
     715                                &retval, argc, args, 0, NULL TSRMLS_CC); 
     716        } 
     717 
     718} 
     719 
     720static GClosure *php_midgard_closure_new(zval *callback, zval *zobject, zval ***args, guint argc TSRMLS_DC) 
     721{ 
     722        GClosure *closure; 
     723        php_mgd_closure *mgdclosure; 
     724 
     725        if(zobject == NULL) { 
     726                 
     727                closure = g_closure_new_simple(sizeof(php_mgd_closure), NULL); 
     728         
     729        } else { 
     730 
     731                php_midgard_gobject *php_gobject = 
     732                        (php_midgard_gobject *)zend_object_store_get_object(zobject TSRMLS_CC); 
     733                 
     734                if(g_type_from_name(Z_OBJCE_P(zobject)->name)) { 
     735 
     736                        GObject *object = G_OBJECT(php_gobject->gobject); 
     737                        closure = g_closure_new_object(sizeof(php_mgd_closure), object); 
     738                 
     739                } else { 
     740                         
     741                        closure = g_closure_new_simple(sizeof(php_mgd_closure), NULL); 
     742                } 
     743        } 
     744         
     745        if(!closure)  
     746                php_error(E_ERROR, "Couldn't create new closure"); 
     747 
     748        mgdclosure = (php_mgd_closure*) closure; 
     749        zval_add_ref(&callback); 
     750        mgdclosure->callback = callback; 
     751        mgdclosure->zobject = zobject; 
     752        mgdclosure->argc = argc; 
     753        mgdclosure->args = NULL; 
     754 
     755        if(args != NULL) { 
     756 
     757                zval_add_ref(*args); 
     758                mgdclosure->args = args;                 
     759        } 
     760         
     761        g_closure_add_invalidate_notifier(closure, NULL, php_midgard_closure_invalidate); 
     762        g_closure_set_marshal((GClosure *)mgdclosure, php_midgard_closure_marshal); 
     763 
     764        return closure; 
     765} 
     766 
     767void php_midgard_gobject_connect(INTERNAL_FUNCTION_PARAMETERS) 
     768{ 
     769        zval *callback; 
     770        gchar *sname = NULL; 
     771        guint sname_length; 
     772        guint signal_id; 
     773        zval *zval_object = getThis(); 
     774        zval *zobject = NULL; 
     775        zval ***args = NULL; 
     776        GQuark signal_detail; 
     777        GClosure *closure = NULL; 
     778        zval ***params_array = NULL; 
     779 
     780        gint argc = ZEND_NUM_ARGS(); 
     781 
     782        /* A function without parameters */ 
     783        if(argc == 2) { 
     784                 
     785                if (zend_parse_parameters(2,  "sz",  
     786                                        &sname, &sname_length, &callback) 
     787                                == FAILURE) { 
     788                        return; 
     789                } 
     790 
     791                argc = 0; 
     792        } 
     793 
     794        /* A method without parameters */ 
     795        if(argc == 3) { 
     796                 
     797                if (zend_parse_parameters(3,  "szo",   
     798                                        &sname, &sname_length, &callback, 
     799                                        &zobject, &args) 
     800                                == FAILURE) { 
     801                        return; 
     802                } 
     803 
     804                argc = 0; 
     805        } 
     806 
     807 
     808        /* A method or function with varargs */ 
     809        if(argc > 3) { 
     810 
     811                args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); 
     812                if (zend_get_parameters_array_ex(argc, args) == FAILURE) { 
     813                        efree(args); 
     814                        WRONG_PARAM_COUNT; 
     815                } 
     816 
     817                /* Keep '!' as passed object parameter can be NULL */ 
     818                if (zend_parse_parameters(3,  "szo!", 
     819                                        &sname, &sname_length, 
     820                                        &callback, &zobject) 
     821                                == FAILURE) { 
     822                        efree(args); 
     823                        return; 
     824                } 
     825 
     826                guint i; 
     827                 
     828                params_array =  
     829                        (zval ***) emalloc(sizeof(zval **)*(argc-3)); 
     830 
     831                for (i = 3; i < argc; i++) { 
     832                         
     833                        params_array[i-3] = args[i]; 
     834                } 
     835 
     836                efree(args); 
     837                /* Do not get signal name, function name and optional object */ 
     838                argc = argc - 3;  
     839        } 
     840 
     841        /* Get underlying GObject instance */ 
     842        php_midgard_gobject *php_gobject = 
     843                (php_midgard_gobject *)zend_object_store_get_object(zval_object TSRMLS_CC); 
     844        GObject *object = G_OBJECT(php_gobject->gobject); 
     845 
     846        if (!g_signal_parse_name(sname, G_OBJECT_TYPE(object),  
     847                                &signal_id, &signal_detail, TRUE)) { 
     848                php_error(E_WARNING, "%s signal name is invalid", sname); 
     849                return; 
     850                /* TODO , should we handle exception here? */ 
     851        } 
     852 
     853        closure = php_midgard_closure_new(callback, zobject, params_array, argc); 
     854 
     855        if(!closure) { 
     856                php_error(E_WARNING, "Can not create new closure"); 
     857                return; 
     858        } 
     859 
     860        g_signal_connect_closure_by_id(object, signal_id, signal_detail, closure, FALSE); 
     861}