[svn:PHP-Sandwich] rev 1072 - PHP-Sandwich/trunk
[email protected] 7 Jun 2005 14:37:36 -0000
| Newsgroups | perl.php.sandwich.dev |
|---|---|
| Message-ID | <[email protected]> |
Author: gschlossnagle
Date: Tue Jun 7 07:37:35 2005
New Revision: 1072
Modified:
PHP-Sandwich/trunk/PHP.xs
PHP-Sandwich/trunk/phpfuncs.c
PHP-Sandwich/trunk/phpfuncs.h
PHP-Sandwich/trunk/phpinterp.c
PHP-Sandwich/trunk/phpinterp.h
Log:
Flesh out support for passing perl classes into PHP, and have them
actable on. The get_class_name thing is a hack, but I think it
is the best solution.
Modified: PHP-Sandwich/trunk/PHP.xs
==============================================================================
--- PHP-Sandwich/trunk/PHP.xs (original)
+++ PHP-Sandwich/trunk/PHP.xs Tue Jun 7 07:37:35 2005
@@ -11,6 +11,7 @@
#endif
#include "phpinterp.h"
+#include "phpfuncs.h"
#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
@@ -54,7 +55,7 @@ static int zval_is_assoc(zval *zptr)
return 0;
}
-zval *SvZval(SV *sv)
+zval *SvZval(SV *sv TSRMLS_DC)
{
SV *orig_sv;
zval *retval = NULL;
@@ -62,7 +63,6 @@ zval *SvZval(SV *sv)
MAKE_STD_ZVAL(retval);
/* derference sv as much as possible */
- fprintf(stderr, "sv: %p\n", sv);
orig_sv = sv;
while(SvROK(sv) && !SvMAGICAL(sv)) {
sv = SvRV(sv);
@@ -103,7 +103,7 @@ zval *SvZval(SV *sv)
for(i = 0; i < cnt; i++) {
element = av_fetch((AV *)sv, i, 0);
if(element) {
- add_index_zval(retval, i, SvZval(*element));
+ add_index_zval(retval, i, SvZval(*element TSRMLS_CC));
}
}
}
@@ -129,7 +129,7 @@ zval *SvZval(SV *sv)
array_init(retval);
hv_iterinit((HV *)sv);
while((element = hv_iternextsv((HV *)sv, &key, &key_len)) != NULL) {
- add_assoc_zval_ex(retval, key, key_len + 1, SvZval(element));
+ add_assoc_zval_ex(retval, key, key_len + 1, SvZval(element TSRMLS_CC));
}
}
break;
@@ -137,8 +137,8 @@ zval *SvZval(SV *sv)
fprintf(stderr, "SVt_PVCV\n");
break;
case SVt_PVGV: /* glob */
- fprintf(stderr, "SVt_PVGV\n");
- sv_dump(sv);
+ /* use orig_sv here to avoid losing your bless */
+ plsv_wrap_sv(retval, orig_sv TSRMLS_CC);
break;
case SVt_PVMG: /* magic */
if(sv_isobject(orig_sv)) {
@@ -147,8 +147,10 @@ zval *SvZval(SV *sv)
retval = prsrc->val;
} else {
/* should wrap me in a zend object */
+ plsv_wrap_sv(retval, orig_sv TSRMLS_CC);
}
} else {
+ fprintf(stderr, "[%s:%d] can I be here?\n", __FILE__, __LINE__);
// do something else
}
break;
@@ -156,7 +158,6 @@ zval *SvZval(SV *sv)
fprintf(stderr, "SVt_PVLV\n");
break;
default:
- fprintf(stderr, "SVt_??? default\n");
ZVAL_NULL(retval);
break;
}
@@ -168,132 +169,143 @@ SV *newSVzval(zval *zptr, PHP_Interprete
SV *retval;
void *old_ctx;
old_ctx = tsrm_set_interpreter_context(interp->ctx);
- switch( zptr->type) {
- case IS_NULL:
- retval = &PL_sv_undef;
- break;
- case IS_LONG:
- retval = newSViv(Z_LVAL_P(zptr));
- break;
- case IS_DOUBLE:
- retval = newSVnv(Z_DVAL_P(zptr));
- break;
- case IS_BOOL:
- retval = Z_BVAL_P(zptr) ? &PL_sv_yes : &PL_sv_no;
- break;
- case IS_ARRAY:
- {
- zval **entry;
- HashPosition pos;
- char *sk;
- uint skl;
- ulong nk;
- int is_assoc = 0;
- if(zval_is_assoc(zptr)) {
- retval = (SV *) newHV();
- is_assoc = 1;
- } else {
- retval = (SV *) newAV();
- is_assoc = 0;
+ {
+ TSRMLS_FETCH();
+ switch( zptr->type) {
+ case IS_NULL:
+ retval = &PL_sv_undef;
+ break;
+ case IS_LONG:
+ retval = newSViv(Z_LVAL_P(zptr));
+ break;
+ case IS_DOUBLE:
+ retval = newSVnv(Z_DVAL_P(zptr));
+ break;
+ case IS_BOOL:
+ retval = Z_BVAL_P(zptr) ? &PL_sv_yes : &PL_sv_no;
+ break;
+ case IS_ARRAY:
+ {
+ zval **entry;
+ HashPosition pos;
+ char *sk;
+ uint skl;
+ ulong nk;
+ int is_assoc = 0;
+ if(zval_is_assoc(zptr)) {
+ retval = (SV *) newHV();
+ is_assoc = 1;
+ } else {
+ retval = (SV *) newAV();
+ is_assoc = 0;
+ }
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zptr), &pos);
+ while(zend_hash_get_current_data_ex(Z_ARRVAL_P(zptr), (void **)&entry, &pos) == SUCCESS) {
+ switch(zend_hash_get_current_key_ex(Z_ARRVAL_P(zptr), &sk, &skl, &nk, 1, &pos)) {
+ case HASH_KEY_IS_STRING:
+ if(!is_assoc) {
+ /* something bad has happened here */
+ }
+ else {
+ hv_store((HV *) retval, sk, skl - 1, newSVzval(*entry, interp), 0);
+ }
+ break;
+ case HASH_KEY_IS_LONG:
+ if(is_assoc) {
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%d", nk);
+ hv_store((HV *) retval, buf, strlen(buf), newSVzval(*entry, interp), 0);
+ } else {
+ av_store((AV *) retval, nk, newSVzval(*entry, interp));
+ }
+ break;
+ }
+ zend_hash_move_forward_ex(Z_ARRVAL_P(zptr), &pos);
+ }
+ retval = newRV_noinc(retval);
}
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zptr), &pos);
- while(zend_hash_get_current_data_ex(Z_ARRVAL_P(zptr), (void **)&entry, &pos) == SUCCESS) {
- switch(zend_hash_get_current_key_ex(Z_ARRVAL_P(zptr), &sk, &skl, &nk, 1, &pos)) {
- case HASH_KEY_IS_STRING:
- if(!is_assoc) {
- /* something bad has happened here */
- }
- else {
- hv_store((HV *) retval, sk, skl - 1, newSVzval(*entry, interp), 0);
+ break;
+ case IS_OBJECT:
+ {
+ char *name;
+ zend_uint namelen;
+ char objectname[MAXPATHLEN];
+ HV *h1, *package;
+ SV * c1;
+ PHP_Class pclass;
+
+ /* this is the special case that this is a perl object returning to us */
+ if(Z_OBJCE_P(zptr) == plsv_ce) {
+ struct plsv *pl;
+ pl = (struct plsv *) zend_object_store_get_object(zptr TSRMLS_CC);
+ SvREFCNT_inc(pl->sv);
+ retval = pl->sv;
+ } else {
+ c1 = newSV(0);
+ pclass = malloc(sizeof(*pclass));
+ /* FIXME: don't leak! */
+
+ MAKE_STD_ZVAL(pclass->val);
+ ZVAL_ZVAL(pclass->val, zptr, 1, 0);
+ pclass->interp = interp;
+ sandwich_interp_inc_ref(interp);
+ if(get_class_name(zptr, &name, &namelen) < 0) {
+ name = "UNKNOWN";
}
- break;
- case HASH_KEY_IS_LONG:
- if(is_assoc) {
- char buf[32];
- snprintf(buf, sizeof(buf), "%d", nk);
- hv_store((HV *) retval, buf, strlen(buf), newSVzval(*entry, interp), 0);
- } else {
- av_store((AV *) retval, nk, newSVzval(*entry, interp));
+ snprintf(objectname, MAXPATHLEN, "PHP::Class::%s", name);
+ sv_setref_pv(c1, "PHP::Class", (void *) pclass);
+ h1 = (HV *)sv_2mortal((SV *)newHV());
+ hv_magic(h1, (GV*)c1, PERL_MAGIC_tied);
+ sv_magic((SV *)h1, c1, PERL_MAGIC_ext, NULL, -1);
+ retval = newRV((SV *)h1);
+ package = gv_stashpv(objectname, TRUE);
+ {
+ char objectisa[MAXPATHLEN];
+ package = gv_stashpv(objectname, 1);
+ snprintf(objectisa, MAXPATHLEN, "PHP::Class::%s::ISA", name);
+ //if(get_av(objectisa, FALSE)) {
+ av_push(get_av(objectisa, TRUE),
+ newSVpv("PHP::Class", 0));
+ //}
}
- break;
+ retval = sv_bless(retval, package);
+ }
}
- zend_hash_move_forward_ex(Z_ARRVAL_P(zptr), &pos);
- }
- retval = newRV_noinc(retval);
- }
- break;
- case IS_OBJECT:
- {
- char *name;
- zend_uint namelen;
- char objectname[MAXPATHLEN];
- HV *h1, *package;
- SV * c1;
- PHP_Class pclass;
-
- c1 = newSV(0);
- pclass = malloc(sizeof(*pclass));
- /* FIXME: don't leak! */
-
- MAKE_STD_ZVAL(pclass->val);
- ZVAL_ZVAL(pclass->val, zptr, 1, 0);
- pclass->interp = interp;
- sandwich_interp_inc_ref(interp);
- if(get_class_name(zptr, &name, &namelen) < 0) {
- name = "UNKNOWN";
- }
- snprintf(objectname, MAXPATHLEN, "PHP::Class::%s", name);
- sv_setref_pv(c1, "PHP::Class", (void *) pclass);
- h1 = (HV *)sv_2mortal((SV *)newHV());
- hv_magic(h1, (GV*)c1, PERL_MAGIC_tied);
- sv_magic((SV *)h1, c1, PERL_MAGIC_ext, NULL, -1);
- retval = newRV((SV *)h1);
- package = gv_stashpv(objectname, TRUE);
+ break;
+ case IS_STRING:
+ retval = newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
+ break;
+ case IS_RESOURCE:
{
- char objectisa[MAXPATHLEN];
- package = gv_stashpv(objectname, 1);
- snprintf(objectisa, MAXPATHLEN, "PHP::Class::%s::ISA", name);
- //if(get_av(objectisa, FALSE)) {
- av_push(get_av(objectisa, TRUE),
- newSVpv("PHP::Class", 0));
- //}
+ SV * c1;
+ PHP_Resource prsrc;
+
+ c1 = newSV(0);
+ prsrc = malloc(sizeof(*prsrc));
+ /* FIXME: don't leak! */
+ MAKE_STD_ZVAL(prsrc->val);
+ ZVAL_ZVAL(prsrc->val, zptr, 1, 0);
+ sandwich_interp_inc_ref(interp);
+ prsrc->interp = interp;
+ sv_setref_pv(c1, "PHP::Resource", (void *) prsrc);
+ retval = newSV(0);
+ sv_magic(retval, c1, PERL_MAGIC_tiedscalar, NULL, 0);
}
- retval = sv_bless(retval, package);
- }
- break;
- case IS_STRING:
- retval = newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
- break;
- case IS_RESOURCE:
- {
- SV * c1;
- PHP_Resource prsrc;
-
- c1 = newSV(0);
- prsrc = malloc(sizeof(*prsrc));
- /* FIXME: don't leak! */
- MAKE_STD_ZVAL(prsrc->val);
- ZVAL_ZVAL(prsrc->val, zptr, 1, 0);
- sandwich_interp_inc_ref(interp);
- prsrc->interp = interp;
- sv_setref_pv(c1, "PHP::Resource", (void *) prsrc);
- retval = newSV(0);
- sv_magic(retval, c1, PERL_MAGIC_tiedscalar, NULL, 0);
- }
- break;
- case IS_CONSTANT:
- retval = newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
- break;
- case IS_CONSTANT_ARRAY:
- fprintf(stderr, "Unimplemented type: IS_CONSTANT_ARRAY\n");
- /* FIXME: return by copy, not by reference */
- retval = &PL_sv_undef;
- break;
- default:
- fprintf(stderr, "Unknown type %d in newSVzval()\n", zptr->type);
- { char *ptr = NULL; *ptr = 1; }
- retval = &PL_sv_undef;
- break;
+ break;
+ case IS_CONSTANT:
+ retval = newSVpv(Z_STRVAL_P(zptr), Z_STRLEN_P(zptr));
+ break;
+ case IS_CONSTANT_ARRAY:
+ fprintf(stderr, "Unimplemented type: IS_CONSTANT_ARRAY\n");
+ /* FIXME: return by copy, not by reference */
+ retval = &PL_sv_undef;
+ break;
+ default:
+ fprintf(stderr, "Unknown type %d in newSVzval()\n", zptr->type);
+ { char *ptr = NULL; *ptr = 1; }
+ retval = &PL_sv_undef;
+ break;
+ }
}
tsrm_set_interpreter_context(old_ctx);
return retval;
@@ -375,103 +387,98 @@ SV *SAND_call(method_name, interp, ...)
char *croakstr = NULL;
old_ctx = tsrm_set_interpreter_context(interp->ctx);
-
- INIT_ZVAL(method);
- ZVAL_STRING(&method, method_name, 1);
- if(items > 2) {
- params = emalloc(sizeof(zval *) * (items - 2));
- for(i = 2; i< items; i++) {
- params[i - 2] = SvZval(ST(i));
- }
- param_count = items - 2;
- }
- retval = sandwich_call_function(interp, &method, params, param_count);
- if(retval == NULL) {
- croakstr = "A PHP error occured";
- goto cleanup;
- } else {
- switch(retval->type) {
- case IS_NULL:
- RETVAL = &PL_sv_undef;
- break;
- case IS_LONG:
- case IS_BOOL:
- case IS_DOUBLE:
- case IS_STRING:
- RETVAL = newSVzval(retval, interp);
- /*
-
- SV * c1 = sv_newmortal();
- RETVAL = newSV(0);
- sv_setref_pv(c1, "PHP::Var::Scalar", (void *) retval);
- sv_magic(RETVAL, c1, PERL_MAGIC_tiedscalar, NULL, 0);
-
- */
- break;
- case IS_ARRAY:
- RETVAL = newSVzval(retval, interp);
- break;
- case IS_OBJECT:
- {
- char *name;
- zend_uint namelen;
- char objectname[MAXPATHLEN];
- HV *h1, *package;
- SV * c1;
- PHP_Class pclass;
-
- c1 = newSV(0);
- pclass = malloc(sizeof(*pclass));
- /* FIXME: don't leak! */
- pclass->val = retval;
- pclass->interp = interp;
- sandwich_interp_inc_ref(interp);
- if(get_class_name(retval, &name, &namelen) < 0) {
- name = "UNKNOWN";
- }
- snprintf(objectname, MAXPATHLEN, "PHP::Class::%s", name);
- sv_setref_pv(c1, "PHP::Class", (void *) pclass);
- h1 = (HV *)sv_2mortal((SV *)newHV());
- hv_magic(h1, (GV*)c1, PERL_MAGIC_tied);
- sv_magic((SV *)h1, c1, PERL_MAGIC_ext, NULL, -1);
- RETVAL = newRV((SV *)h1);
- package = gv_stashpv(objectname, TRUE);
- {
- char objectisa[MAXPATHLEN];
- package = gv_stashpv(objectname, 1);
- snprintf(objectisa, MAXPATHLEN, "PHP::Class::%s::ISA", name);
- //if(get_av(objectisa, FALSE)) {
- av_push(get_av(objectisa, TRUE),
- newSVpv("PHP::Class", 0));
- //}
- }
- RETVAL = sv_bless(RETVAL, package);
- }
- break;
- case IS_RESOURCE:
+ {
+ TSRMLS_FETCH();
+ INIT_ZVAL(method);
+ ZVAL_STRING(&method, method_name, 1);
+ if(items > 2) {
+ params = emalloc(sizeof(zval *) * (items - 2));
+ for(i = 2; i< items; i++) {
+ params[i - 2] = SvZval(ST(i) TSRMLS_CC);
+ }
+ param_count = items - 2;
+ }
+ retval = sandwich_call_function(interp, &method, params, param_count);
+ if(retval == NULL) {
+ croakstr = "A PHP error occured";
+ goto cleanup;
+ } else {
+ RETVAL = newSVzval(retval, interp);
+ /*
+ switch(retval->type) {
+ case IS_NULL:
+ RETVAL = &PL_sv_undef;
+ break;
+ case IS_LONG:
+ case IS_BOOL:
+ case IS_DOUBLE:
+ case IS_STRING:
+ RETVAL = newSVzval(retval, interp);
+ break;
+ case IS_ARRAY:
+ RETVAL = newSVzval(retval, interp);
+ break;
+ case IS_OBJECT:
{
+ char *name;
+ zend_uint namelen;
+ char objectname[MAXPATHLEN];
+ HV *h1, *package;
SV * c1;
- PHP_Resource prsrc;
-
+ PHP_Class pclass;
+
c1 = newSV(0);
- prsrc = malloc(sizeof(*prsrc));
- /* FIXME: don't leak! */
- prsrc->val = retval;
+ pclass = malloc(sizeof(*pclass));
+ pclass->val = retval;
+ pclass->interp = interp;
sandwich_interp_inc_ref(interp);
- prsrc->interp = interp;
- RETVAL = newSV(0);
- sv_setref_pv(c1, "PHP::Resource", (void *) prsrc);
- sv_magic(RETVAL, c1, PERL_MAGIC_tiedscalar, NULL, 0);
+ if(get_class_name(retval, &name, &namelen) < 0) {
+ name = "UNKNOWN";
+ }
+ snprintf(objectname, MAXPATHLEN, "PHP::Class::%s", name);
+ sv_setref_pv(c1, "PHP::Class", (void *) pclass);
+ h1 = (HV *)sv_2mortal((SV *)newHV());
+ hv_magic(h1, (GV*)c1, PERL_MAGIC_tied);
+ sv_magic((SV *)h1, c1, PERL_MAGIC_ext, NULL, -1);
+ RETVAL = newRV((SV *)h1);
+ package = gv_stashpv(objectname, TRUE);
+ {
+ char objectisa[MAXPATHLEN];
+ package = gv_stashpv(objectname, 1);
+ snprintf(objectisa, MAXPATHLEN, "PHP::Class::%s::ISA", name);
+ //if(get_av(objectisa, FALSE)) {
+ av_push(get_av(objectisa, TRUE),
+ newSVpv("PHP::Class", 0));
+ //}
+ }
+ RETVAL = sv_bless(RETVAL, package);
}
- break;
- default:
- fprintf(stderr, "unsupported return type in PHP_Interpreter_call\n");
- RETVAL = &PL_sv_undef;
- break;
+ break;
+ case IS_RESOURCE:
+ {
+ SV * c1;
+ PHP_Resource prsrc;
+
+ c1 = newSV(0);
+ prsrc = malloc(sizeof(*prsrc));
+ prsrc->val = retval;
+ sandwich_interp_inc_ref(interp);
+ prsrc->interp = interp;
+ RETVAL = newSV(0);
+ sv_setref_pv(c1, "PHP::Resource", (void *) prsrc);
+ sv_magic(RETVAL, c1, PERL_MAGIC_tiedscalar, NULL, 0);
+ }
+ break;
+ default:
+ fprintf(stderr, "unsupported return type in PHP_Interpreter_call\n");
+ RETVAL = &PL_sv_undef;
+ break;
+ }
+ */
}
+ cleanup:
+ zval_dtor(&method);
}
-cleanup:
- zval_dtor(&method);
tsrm_set_interpreter_context(old_ctx);
if(croakstr) croak(croakstr);
}
@@ -517,7 +524,7 @@ SV* SAND_instantiate(interp, class, ...)
if(items > 2) {
params = emalloc(sizeof(zval **) * (items - 2));
for(i = 2; i< items; i++) {
- zval *arg = SvZval(ST(i));
+ zval *arg = SvZval(ST(i) TSRMLS_CC);
params[i - 2] = &arg;
}
param_count = items - 2;
@@ -593,7 +600,7 @@ SV* PHP_V_C_STORE(pclass, key, value)
TSRMLS_FETCH();
ce = zend_get_class_entry(pclass->val TSRMLS_CC);
- tostore = SvZval(value);
+ tostore = SvZval(value TSRMLS_CC);
if(tostore) zend_update_property(ce, pclass->val, key, strlen(key), tostore TSRMLS_CC);
else croak("problem converting perl type to SV");
RETVAL = newSVsv(value);
@@ -777,7 +784,7 @@ SV *PHP_V_C__AUTOLOAD(self, method_name,
if(items > 2) {
params = emalloc(sizeof(zval **) * (items - 2));
for(i = 2; i< items; i++) {
- zval *arg = SvZval(ST(i));
+ zval *arg = SvZval(ST(i) TSRMLS_CC);
params[i - 2] = &arg;
}
param_count = items - 2;
Modified: PHP-Sandwich/trunk/phpfuncs.c
==============================================================================
--- PHP-Sandwich/trunk/phpfuncs.c (original)
+++ PHP-Sandwich/trunk/phpfuncs.c Tue Jun 7 07:37:35 2005
@@ -8,10 +8,13 @@
ZEND_DECLARE_MODULE_GLOBALS(sandwich);
zend_class_entry *pl_ce;
zend_class_entry *plobj_ce;
+zend_class_entry *plsv_ce;
static zend_object_handlers plobj_handlers;
+static zend_object_handlers plsv_handlers;
static zend_object_value plobj_create_object(zend_class_entry *ce TSRMLS_DC);
+static zend_object_value plsv_create_object(zend_class_entry *ce TSRMLS_DC);
PHP_MINFO_FUNCTION(sandwich)
@@ -67,7 +70,7 @@ sandwich_dim_read(zval *obj, zval *offse
goto err_out;
}
- return_value = SvZval(value);
+ return_value = SvZval(value TSRMLS_CC);
return return_value;
err_out:
@@ -120,7 +123,7 @@ PHP_METHOD(perl, getvariable)
}
if (var != NULL) {
- retval = SvZval(var);
+ retval = SvZval(var TSRMLS_CC);
RETURN_ZVAL(retval, 1, 0);
} else {
RETURN_NULL();
@@ -225,7 +228,7 @@ static int _sandwich_call_method(char *m
*/
SvREFCNT_inc(prv);
PUTBACK;
- retval = SvZval(prv);
+ retval = SvZval(prv TSRMLS_CC);
RETURN_ZVAL(retval, 1, 0);
SvREFCNT_dec(prv);
FREETMPS;
@@ -351,12 +354,134 @@ PHP_METHOD(perl, eval)
if((rv = sandwich_perl_eval(aTHX_ func)) == NULL) {
fprintf(stderr, "eval returned null\n");
} else {
- zval *retval = SvZval(rv);
+ zval *retval = SvZval(rv TSRMLS_CC);
RETURN_ZVAL(retval, 1, 0);
SvREFCNT_dec(rv);
}
}
+static int _sv_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS, int offset)
+{
+ struct plsv *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);
+#ifdef USE_ITHREADS
+ aTHX = pl->perl;
+#endif
+ {
+ 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);
+#ifdef USE_ITHREADS
+ aTHX = pl->perl;
+#endif
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ SvREFCNT_inc(pl->sv);
+ XPUSHs(pl->sv);
+ for(i = offset; i < argc; i++) {
+ var = newSVzval(*args[i], SandwichG(php));
+ var = sv_2mortal(var);
+ XPUSHs(var);
+ }
+ PUTBACK;
+ call_method(method, G_SCALAR);
+ SvREFCNT_dec(pl->sv);
+ SPAGAIN;
+ prv = POPs;
+ /*
+ if(coe && SvTRUE(ERRSV)) {
+ croak(SvPVx(ERRSV, n_a));
+ }
+ */
+ SvREFCNT_inc(prv);
+ PUTBACK;
+ retval = SvZval(prv TSRMLS_CC);
+ RETURN_ZVAL(retval, 1, 0);
+ SvREFCNT_dec(prv);
+ FREETMPS;
+ LEAVE;
+ efree(args);
+ }
+}
+
+static PHP_FUNCTION(sv_method_handler)
+{
+ _sv_call_method(
+ ((zend_internal_function*)EG(function_state_ptr)->function)->function_name,
+ INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+
+static int sv_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
+{
+ return _sv_call_method(method, INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+
+static union _zend_function *sv_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(sv_method_handler);
+
+ func = emalloc(sizeof(*func));
+ memcpy(func, &f,sizeof(f));
+ return func;
+}
+
+int sv_get_class_name(zval *obj, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) {
+ if(parent) {
+ *class_name_len = strlen("PerlSV") + 1;
+ *class_name = estrndup("PerlSV", *class_name_len);
+ } else {
+ struct plsv *pl;
+ char *tmp;
+ pl = (struct plsv *) zend_object_store_get_object(obj TSRMLS_CC);
+ tmp = HvNAME((SvSTASH(SvRV(pl->sv))));
+ if(!tmp) return FAILURE;
+ *class_name_len = strlen(tmp) + sizeof("PerlSV::");
+ *class_name = emalloc(*class_name_len);
+ strncpy(*class_name, "PerlSV::", sizeof("PerlSV::"));
+ strcat(*class_name, tmp);
+ return SUCCESS;
+ }
+}
+
static function_entry pl_functions[] = {
PHP_ME(perl, getinstance, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
{NULL, NULL, NULL}
@@ -370,6 +495,10 @@ static function_entry plobj_functions[]
{NULL, NULL, NULL}
};
+static function_entry plsv_functions[] = {
+ {NULL, NULL, NULL}
+};
+
static void
plobj_free(void *obj TSRMLS_DC)
{
@@ -438,12 +567,101 @@ plobj_create_object(zend_class_entry *ce
return obj;
}
+
+
+static void
+plsv_free(void *obj TSRMLS_DC)
+{
+ struct plsv *pl;
+
+ pl = (struct plsv *) obj;
+ zend_hash_destroy(pl->zo.properties);
+ FREE_HASHTABLE(pl->zo.properties);
+
+ efree(obj);
+}
+
+static void
+plsv_dtor(void *obj, zend_object_handle handle TSRMLS_DC)
+{
+ struct plsv *pl;
+ dTHX;
+
+ pl = (struct plsv *) obj;
+ SvREFCNT_dec(pl->sv);
+}
+
+static struct plsv *
+plsv_new(zend_class_entry *ce TSRMLS_DC)
+{
+ struct plsv *pl;
+ zend_object_value obj;
+ dTHX;
+
+ pl = ecalloc(1, sizeof(*pl));
+ pl->zo.ce = ce;
+
+ ALLOC_HASHTABLE(pl->zo.properties);
+ zend_hash_init(pl->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+#ifdef USE_ITHREADS
+ pl->perl = aTHX;
+#endif
+
+ return pl;
+}
+
+static void
+plsv_clone(void *obj, void **cp TSRMLS_DC)
+{
+ struct plsv *pl;
+ struct plsv *clone;
+
+ pl = (struct plsv *) obj;
+
+ clone = plsv_new(pl->zo.ce TSRMLS_CC);
+ if (!clone) {
+ *cp = NULL;
+ return;
+ }
+
+ *cp = (void *) clone;
+}
+
+static zend_object_value
+plsv_create_object(zend_class_entry *ce TSRMLS_DC)
+{
+ struct plsv *pl;
+ zend_object_value obj;
+
+ pl = plsv_new(ce TSRMLS_CC);
+
+ obj.handle = zend_objects_store_put(pl, plsv_dtor,
+ (zend_objects_free_object_storage_t) plsv_free, plsv_clone TSRMLS_CC);
+ obj.handlers = (zend_object_handlers *) &plsv_handlers;
+
+ return obj;
+}
+
+void plsv_wrap_sv(zval *retval, SV *sv TSRMLS_DC)
+{
+ struct plsv *pl;
+
+ object_init_ex(retval, plsv_ce);
+ retval->refcount = 1;
+ retval->is_ref = 1;
+
+ pl = (struct plsv *) zend_object_store_get_object(retval TSRMLS_CC);
+ SvREFCNT_inc(sv);
+ pl->sv = sv;
+}
PHP_MINIT_FUNCTION(sandwich)
{
zend_class_entry pl;
zend_class_entry plobj;
+ zend_class_entry plsv;
ZEND_INIT_MODULE_GLOBALS(sandwich, sw_initglobals, NULL);
@@ -468,7 +686,23 @@ PHP_MINIT_FUNCTION(sandwich)
plobj_handlers.write_dimension = sandwich_dim_write;
plobj_handlers.get_method = sandwich_get_method;
plobj_handlers.call_method = sandwich_call_method;
+
+ INIT_CLASS_ENTRY(plsv, "PerlSV", plsv_functions);
+ plsv.create_object = plsv_create_object;
+ plsv_ce = zend_register_internal_class(&plsv TSRMLS_CC);
+ if (!plsv_ce) {
+ return FAILURE;
+ }
+
+ memcpy(&plsv_handlers, zend_get_std_object_handlers(),
+ sizeof(plsv_handlers));
+
+ plsv_handlers.read_dimension = sandwich_dim_read;
+ plsv_handlers.write_dimension = sandwich_dim_write;
+ plsv_handlers.get_method = sv_get_method;
+ plsv_handlers.call_method = sv_call_method;
+ plsv_handlers.get_class_name = sv_get_class_name;
return SUCCESS;
}
Modified: PHP-Sandwich/trunk/phpfuncs.h
==============================================================================
--- PHP-Sandwich/trunk/phpfuncs.h (original)
+++ PHP-Sandwich/trunk/phpfuncs.h Tue Jun 7 07:37:35 2005
@@ -21,11 +21,24 @@ struct plobj {
PerlInterpreter *perl;
};
+struct plsv {
+ zend_object zo;
+ SV *sv;
+ PerlInterpreter *perl;
+};
+
struct perlistats {
uint16_t ps_callcnt;
uint16_t ps_varcnt;
};
+extern ZEND_API zend_class_entry *pl_ce;
+extern ZEND_API zend_class_entry *plobj_ce;
+extern ZEND_API zend_class_entry *plsv_ce;
+
+void plsv_wrap_sv(zval *retval, SV *sv TSRMLS_DC);
+
+
ZEND_BEGIN_MODULE_GLOBALS(sandwich)
struct perlistats ps_stats;
sandwich_per_interp *php;
Modified: PHP-Sandwich/trunk/phpinterp.c
==============================================================================
--- PHP-Sandwich/trunk/phpinterp.c (original)
+++ PHP-Sandwich/trunk/phpinterp.c Tue Jun 7 07:37:35 2005
@@ -237,7 +237,7 @@ SV *sandwich_eval(sandwich_per_interp *i
cleanup:
tsrm_set_interpreter_context(old_ctx);
if(rv == -1) {
- croak("error in eval");
+ croak("PHP Error in eval");
} else {
/* FIXME, do i need to copy retval? */
return newSVzval(&retval, interp);
Modified: PHP-Sandwich/trunk/phpinterp.h
==============================================================================
--- PHP-Sandwich/trunk/phpinterp.h (original)
+++ PHP-Sandwich/trunk/phpinterp.h Tue Jun 7 07:37:35 2005
@@ -38,7 +38,7 @@ zval *sandwich_call_function(sandwich_pe
#define sandwich_interp_inc_ref(interp) interp->ref++
#define sandwich_interp_dec_ref(interp) if(--interp->ref == 0) sandwich_per_interp_shutdown(interp)
-zval *SvZval(SV *sv);
+zval *SvZval(SV *sv TSRMLS_DC);
SV *newSVzval(zval *param, sandwich_per_interp *interp);
#endif