[svn:PHP-Sandwich] rev 1042 - in PHP-Sandwich/trunk: . t

[email protected] 6 May 2005 17:46:14 -0000
Newsgroups perl.php.sandwich.dev
Message-ID <[email protected]>
Author: gschlossnagle
Date: Fri May  6 10:46:14 2005
New Revision: 1042

Modified:
   PHP-Sandwich/trunk/phpfuncs.c
   PHP-Sandwich/trunk/t/15.t
Log:
enable overloading style calls to perl methods from
PHP


Modified: PHP-Sandwich/trunk/phpfuncs.c
==============================================================================
--- PHP-Sandwich/trunk/phpfuncs.c	(original)
+++ PHP-Sandwich/trunk/phpfuncs.c	Fri May  6 10:46:14 2005
@@ -28,7 +28,7 @@
 }
 
 static zval *
-perl_dim_read(zval *obj, zval *offset, int type TSRMLS_DC)
+sandwich_dim_read(zval *obj, zval *offset, int type TSRMLS_DC)
 {
   SV           *value;
   zval         *return_value;
@@ -75,7 +75,7 @@
 }
 
 static void
-perl_dim_write(zval *obj, zval *offset, zval *value TSRMLS_DC)
+sandwich_dim_write(zval *obj, zval *offset, zval *value TSRMLS_DC)
 {
   return;
 }
@@ -181,46 +181,141 @@
   SV           *sparam;
   SV           *prv;
   pTHX;
-  dSP;
+  pl = zend_object_store_get_object(getThis() TSRMLS_CC);
+  aTHX = pl->perl;
 
-  argc = ZEND_NUM_ARGS();
-  if(argc < 1) {
-    WRONG_PARAM_COUNT;
-  }
-  args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0);
-  if(zend_get_parameters_array_ex(argc, args) == FAILURE) {
+  {
+    dSP;
+  
+    argc = ZEND_NUM_ARGS();
+    if(argc < 1) {
+      WRONG_PARAM_COUNT;
+    }
+    args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0);
+    if(zend_get_parameters_array_ex(argc, args) == FAILURE) {
+      efree(args);
+      WRONG_PARAM_COUNT;
+    }
+    name = Z_STRVAL_PP(args[0]);
+    
+    ENTER;
+    SAVETMPS;
+    PUSHMARK(SP);
+    for(i = 1; i < argc; i++) {
+      var = sv_2mortal(newSVzval(*args[i], SandwichG(php)));
+      XPUSHs(var);
+    }
+    PUTBACK;
+    call_pv(name, G_SCALAR);
+    SPAGAIN;
+    prv = POPs;
+    /*
+    if(coe && SvTRUE(ERRSV)) {
+      croak(SvPVx(ERRSV, n_a));
+    }
+    */
+    SvREFCNT_inc(prv);
+    PUTBACK;
+    retval = SvZval(prv);
+    RETURN_ZVAL(retval, 1, 0);
+    SvREFCNT_dec(prv);
+    FREETMPS;
+    LEAVE;
     efree(args);
-    WRONG_PARAM_COUNT;
   }
-  name = Z_STRVAL_PP(args[0]);
-  
+}
+
+static int sandwich_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
+{
+  struct plobj *pl;
+  SV           *var;
+  zval         *retval;
+  char         *name;
+  int           namelen;
+  zval         *param;
+  zval         ***args;
+  SV           *sparam;
+  int          argc, i;
+  SV           *prv;
+  pTHX;
+
   pl = zend_object_store_get_object(getThis() TSRMLS_CC);
   aTHX = pl->perl;
-
-  ENTER;
-  SAVETMPS;
-  PUSHMARK(SP);
-  for(i = 1; i < argc; i++) {
-    var = sv_2mortal(newSVzval(*args[i], SandwichG(php)));
-    XPUSHs(var);
-  }
-  PUTBACK;
-  call_pv(name, G_SCALAR);
-  SPAGAIN;
-  prv = POPs;
-  /*
-  if(coe && SvTRUE(ERRSV)) {
-    croak(SvPVx(ERRSV, n_a));
+  {
+    dSP;
+  
+    argc = ZEND_NUM_ARGS();
+    args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0);
+    if(zend_get_parameters_array_ex(argc, args) == FAILURE) {
+      efree(args);
+      WRONG_PARAM_COUNT;
+    }
+    
+    pl = zend_object_store_get_object(getThis() TSRMLS_CC);
+    aTHX = pl->perl;
+  
+    ENTER;
+    SAVETMPS;
+    PUSHMARK(SP);
+    for(i = 0; i < argc; i++) {
+      var = newSVzval(*args[i], SandwichG(php));
+      var = sv_2mortal(var);
+      XPUSHs(var);
+    }
+    PUTBACK;
+    call_pv(method, G_SCALAR);
+    SPAGAIN;
+    prv = POPs;
+    /*
+    if(coe && SvTRUE(ERRSV)) {
+      croak(SvPVx(ERRSV, n_a));
+    }
+    */
+    SvREFCNT_inc(prv);
+    PUTBACK;
+    retval = SvZval(prv);
+    RETURN_ZVAL(retval, 1, 0);
+    SvREFCNT_dec(prv);
+    FREETMPS;
+    LEAVE;
+    efree(args);
   }
-  */
-  SvREFCNT_inc(prv);
-  PUTBACK;
-  retval = SvZval(prv);
-  RETURN_ZVAL(retval, 1, 0);
-  SvREFCNT_dec(prv);
-  FREETMPS;
-  LEAVE;
-  efree(args);
+}
+
+static PHP_FUNCTION(sandwich_method_handler)
+{
+  sandwich_call_method(
+    ((zend_internal_function*)EG(function_state_ptr)->function)->function_name,
+    INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static union _zend_function *sandwich_get_method(zval **object_ptr, char *name, int len TSRMLS_DC)
+{
+  zval *object = *object_ptr;
+  zend_internal_function f, *fptr = NULL;
+  union _zend_function *func;
+  struct plobj *pl;
+  char *lc_method_name;
+
+  lc_method_name = emalloc(len + 1);
+  zend_str_tolower_copy(lc_method_name, name, len);
+  if (zend_hash_find(&plobj_ce->function_table, lc_method_name, len+1, (void**)&func) == SUCCESS) {
+    efree(lc_method_name);
+    return func;
+  }
+  efree(lc_method_name);
+  
+  f.type = ZEND_OVERLOADED_FUNCTION;
+  f.num_args = 0;
+  f.arg_info = NULL;
+  f.scope = plobj_ce;
+  f.fn_flags=0;
+  f.function_name= estrndup(name, len);
+  f.handler= PHP_FN(sandwich_method_handler);
+
+  func = emalloc(sizeof(*func));
+  memcpy(func, &f,sizeof(f));
+  return func;
 }
 
 PHP_METHOD(perl, getinstance)
@@ -396,8 +491,10 @@
   memcpy(&plobj_handlers, zend_get_std_object_handlers(), 
       sizeof(plobj_handlers));
 
-  plobj_handlers.read_dimension = perl_dim_read;
-  plobj_handlers.write_dimension = perl_dim_write;
+  plobj_handlers.read_dimension = sandwich_dim_read;
+  plobj_handlers.write_dimension = sandwich_dim_write;
+  plobj_handlers.get_method = sandwich_get_method;
+  plobj_handlers.call_method = sandwich_call_method;
   
   return SUCCESS;
 }

Modified: PHP-Sandwich/trunk/t/15.t
==============================================================================
--- PHP-Sandwich/trunk/t/15.t	(original)
+++ PHP-Sandwich/trunk/t/15.t	Fri May  6 10:46:14 2005
@@ -1,6 +1,6 @@
 #!/opt/ecelerity/3rdParty/bin/perl
 use strict;
-use Test::More tests => 5;
+use Test::More tests => 7;
 
 BEGIN {
     diag "Testing Perl::call";
@@ -24,3 +24,11 @@
 /), 'Test use of Perl::call';
 
 is $rv, 'hello world', "Check return value of call";
+
+ok $rv = $p->eval(q/
+  $perl = Perl::getInstance();
+  $rv = $perl->hello('world');
+  return $rv;
+/), 'Test use of Perl::call via PHP overloading';
+
+is $rv, 'hello world', "Check return value of call";