diff options
Diffstat (limited to 'Lib/php')
-rw-r--r-- | Lib/php/argcargv.i | 38 | ||||
-rw-r--r-- | Lib/php/const.i | 68 | ||||
-rw-r--r-- | Lib/php/director.swg | 48 | ||||
-rw-r--r-- | Lib/php/factory.i | 70 | ||||
-rw-r--r-- | Lib/php/globalvar.i | 293 | ||||
-rw-r--r-- | Lib/php/php.swg | 342 | ||||
-rw-r--r-- | Lib/php/phpinit.swg | 19 | ||||
-rw-r--r-- | Lib/php/phpinterfaces.i | 60 | ||||
-rw-r--r-- | Lib/php/phpkw.swg | 60 | ||||
-rw-r--r-- | Lib/php/phppointers.i | 48 | ||||
-rw-r--r-- | Lib/php/phprun.swg | 271 | ||||
-rw-r--r-- | Lib/php/std_auto_ptr.i | 41 | ||||
-rw-r--r-- | Lib/php/std_common.i | 1 | ||||
-rw-r--r-- | Lib/php/std_map.i | 19 | ||||
-rw-r--r-- | Lib/php/std_string.i | 75 | ||||
-rw-r--r-- | Lib/php/std_string_view.i | 69 | ||||
-rw-r--r-- | Lib/php/std_unique_ptr.i | 41 | ||||
-rw-r--r-- | Lib/php/std_vector.i | 2 | ||||
-rw-r--r-- | Lib/php/stl.i | 1 | ||||
-rw-r--r-- | Lib/php/swigmove.i | 24 | ||||
-rw-r--r-- | Lib/php/typemaps.i | 60 | ||||
-rw-r--r-- | Lib/php/utils.i | 33 |
22 files changed, 884 insertions, 799 deletions
diff --git a/Lib/php/argcargv.i b/Lib/php/argcargv.i new file mode 100644 index 000000000..2a0d745de --- /dev/null +++ b/Lib/php/argcargv.i @@ -0,0 +1,38 @@ +/* ------------------------------------------------------------- + * SWIG library containing argc and argv multi-argument typemaps + * ------------------------------------------------------------- */ + +%typemap(in) (int ARGC, char **ARGV) { + int len, i; + zval *val; + zend_array *ar; + if (Z_TYPE($input) != IS_ARRAY) { + SWIG_PHP_Error(E_ERROR, "Type error in '$symname'. Expected array"); + goto fail; + } + ar = Z_ARR($input); + len = zend_array_count(ar); + $1 = ($1_ltype) len; + $2 = (char **) malloc((len+1)*sizeof(char *)); + i = 0; + ZEND_HASH_FOREACH_VAL(ar, val) { + if (Z_TYPE(*val) != IS_STRING) { + SWIG_PHP_Error(E_ERROR, "Array must use strings only, in '$symname'."); + goto fail; + } + if (i == len) { + SWIG_PHP_Error(E_ERROR, "Array is bigger than zend report in '$symname'."); + goto fail; + } + $2[i++] = Z_STRVAL(*val); + } ZEND_HASH_FOREACH_END(); + $2[i] = NULL; +} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) { + $1 = Z_TYPE($input) == IS_ARRAY; +} + +%typemap(freearg) (int ARGC, char **ARGV) { + free((void *)$2); +} diff --git a/Lib/php/const.i b/Lib/php/const.i index 32b4b9b0b..1e1fe9cad 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -3,6 +3,58 @@ * * Typemaps for constants * ----------------------------------------------------------------------------- */ +%typemap(classconsttab) int, + unsigned int, + short, + unsigned short, + long, + unsigned long, + unsigned char, + signed char, + enum SWIGTYPE %{ + zend_declare_class_constant_long(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)($value)); +%} + +%typemap(classconsttab) bool %{ + zend_declare_class_constant_bool(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)($value)); +%} + +%typemap(classconsttab) float, + double %{ + zend_declare_class_constant_double(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, $value); +%} + +%typemap(classconsttab) char %{ +{ + char swig_char = $value; + zend_declare_class_constant_stringl(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, &swig_char, 1); +} +%} + +%typemap(classconsttab) char *, + const char *, + char [], + const char [] %{ + zend_declare_class_constant_string(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, $value); +%} + +// This creates a zend_object to wrap the pointer, and we can't do that +// before the Zend runtime has been initialised so we delay it until +// RINIT. The downside is it then happens for every request. +%typemap(classconsttab,rinit=1) SWIGTYPE *, + SWIGTYPE &, + SWIGTYPE &&, + SWIGTYPE [] %{ +{ + zval z; + ZVAL_UNDEF(&z); + SWIG_SetPointerZval(&z, (void*)($value), $1_descriptor, 0); + zval_copy_ctor(&z); + zend_declare_class_constant(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, &z); +} +%} + +%typemap(classconsttab) SWIGTYPE (CLASS::*) "" %typemap(consttab) int, unsigned int, @@ -13,10 +65,10 @@ unsigned char, signed char, enum SWIGTYPE - "SWIG_LONG_CONSTANT($symname, ($1_type)$value);"; + "SWIG_LONG_CONSTANT($symname, ($1_type)($value));"; %typemap(consttab) bool - "SWIG_BOOL_CONSTANT($symname, ($1_type)$value);"; + "SWIG_BOOL_CONSTANT($symname, ($1_type)($value));"; %typemap(consttab) float, double @@ -31,17 +83,21 @@ const char [] "SWIG_STRING_CONSTANT($symname, $value);"; -%typemap(consttab) SWIGTYPE *, +// This creates a zend_object to wrap the pointer, and we can't do that +// before the Zend runtime has been initialised so we delay it until +// RINIT. The downside is it then happens for every request. +%typemap(consttab,rinit=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { zend_constant c; - SWIG_SetPointerZval(&c.value, (void*)$value, $1_descriptor, 0); + ZVAL_UNDEF(&c.value); + SWIG_SetPointerZval(&c.value, (void*)($value), $1_descriptor, 0); zval_copy_ctor(&c.value); c.name = zend_string_init("$symname", sizeof("$symname") - 1, 0); - SWIG_ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, module_number); + ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, module_number); zend_register_constant(&c); } /* Handled as a global variable. */ -%typemap(consttab) SWIGTYPE (CLASS::*) ""; +%typemap(consttab) SWIGTYPE (CLASS::*) "" diff --git a/Lib/php/director.swg b/Lib/php/director.swg index ea0eba8ac..55ffff516 100644 --- a/Lib/php/director.swg +++ b/Lib/php/director.swg @@ -8,6 +8,8 @@ #ifndef SWIG_DIRECTOR_PHP_HEADER_ #define SWIG_DIRECTOR_PHP_HEADER_ +#define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG) + #include <string> #include <exception> #include <map> @@ -76,31 +78,34 @@ namespace Swig { }; class Director { + private: + /* flag indicating whether the object is owned by PHP or C++ */ + mutable bool swig_disown_flag; + protected: // "mutable" so we can get a non-const pointer to it in const methods. mutable zval swig_self; typedef std::map<void *, GCItem_var> swig_ownership_map; mutable swig_ownership_map swig_owner; + public: - Director(zval *self) { + Director(zval *self) : swig_disown_flag(false) { ZVAL_COPY_VALUE(&swig_self, self); } - static bool swig_is_overridden_method(const char *cname, const char *lc_fname) { - bool result = false; - zend_string * cname_str = zend_string_init(cname, strlen(cname), 0); - zend_class_entry *ce = zend_lookup_class(cname_str); - if (ce) { - zval * mptr = zend_hash_str_find(&ce->function_table, lc_fname, strlen(lc_fname)); - if (mptr) { - // common.scope points to zend_class_entry for the declaring class, - // and there's only one of those per class, so we can just use a - // pointer compare here. - result = Z_FUNC_P(mptr)->common.scope != ce; - } + ~Director() { + if (swig_disown_flag) { + Z_DELREF(swig_self); + } + } + + zend_object *swig_get_self() const { return Z_OBJ(swig_self); } + + void swig_disown() const { + if (!swig_disown_flag) { + swig_disown_flag = true; + Z_ADDREF(swig_self); } - zend_string_release(cname_str); - return result; } template <typename Type> @@ -109,6 +114,12 @@ namespace Swig { swig_owner[vptr] = new GCItem_T<Type>(vptr); } } + + void swig_acquire_ownership_obj(void *vptr, int own) const { + if (vptr && own) { + swig_owner[vptr] = new GCItem_Object(own); + } + } }; /* base class for director exceptions */ @@ -121,8 +132,8 @@ namespace Swig { swig_msg += " "; swig_msg += msg; } - SWIG_ErrorCode() = code; - SWIG_ErrorMsg() = swig_msg.c_str(); + // Don't replace an already active PHP exception. + if (!EG(exception)) zend_throw_exception(NULL, swig_msg.c_str(), code); } virtual ~DirectorException() throw() { @@ -150,8 +161,7 @@ namespace Swig { }; /* any php exception that occurs during a director method call */ - class DirectorMethodException : public DirectorException - { + class DirectorMethodException : public DirectorException { public: DirectorMethodException() : DirectorException(E_ERROR, "SWIG director method error", NULL) { diff --git a/Lib/php/factory.i b/Lib/php/factory.i index c4e082dd2..5f2b397ec 100644 --- a/Lib/php/factory.i +++ b/Lib/php/factory.i @@ -3,41 +3,41 @@ you have: ---- geometry.h -------- - struct Geometry { - enum GeomType{ - POINT, - CIRCLE - }; - - virtual ~Geometry() {} + struct Geometry { + enum GeomType{ + POINT, + CIRCLE + }; + + virtual ~Geometry() {} virtual int draw() = 0; - + // // Factory method for all the Geometry objects // - static Geometry *create(GeomType i); - }; - - struct Point : Geometry { - int draw() { return 1; } - double width() { return 1.0; } - }; - - struct Circle : Geometry { - int draw() { return 2; } - double radius() { return 1.5; } - }; - + static Geometry *create(GeomType i); + }; + + struct Point : Geometry { + int draw() { return 1; } + double width() { return 1.0; } + }; + + struct Circle : Geometry { + int draw() { return 2; } + double radius() { return 1.5; } + }; + // // Factory method for all the Geometry objects // Geometry *Geometry::create(GeomType type) { - switch (type) { - case POINT: return new Point(); - case CIRCLE: return new Circle(); - default: return 0; - } - } + switch (type) { + case POINT: return new Point(); + case CIRCLE: return new Circle(); + default: return 0; + } + } ---- geometry.h -------- @@ -57,16 +57,16 @@ NOTES: remember to fully qualify all the type names and don't use %factory inside a namespace declaration, ie, instead of - + namespace Foo { %factory(Geometry *Geometry::create, Point, Circle); } use - %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle); + %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle); + - */ /* for loop for macro with one argument */ @@ -90,20 +90,20 @@ /* for loop for macro with two arguments */ %define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef -%define %_factory_dispatch(Type) +%define %_factory_dispatch(Type) if (!dcast) { Type *dobj = dynamic_cast<Type *>($1); if (dobj) { dcast = 1; - SWIG_SetPointerZval(return_value, SWIG_as_voidptr(dobj),$descriptor(Type *), $owner); - } + SWIG_SetPointerZval(return_value, SWIG_as_voidptr(dobj), $descriptor(Type *), $owner); + } }%enddef %define %factory(Method,Types...) -%typemap(out) Method { +%typemap(out, phptype="?SWIGTYPE") Method { int dcast = 0; %formacro(%_factory_dispatch, Types) if (!dcast) { - SWIG_SetPointerZval(return_value, SWIG_as_voidptr($1),$descriptor, $owner); + SWIG_SetPointerZval(return_value, SWIG_as_voidptr($1), $descriptor, $owner); } }%enddef diff --git a/Lib/php/globalvar.i b/Lib/php/globalvar.i deleted file mode 100644 index 6b31207a6..000000000 --- a/Lib/php/globalvar.i +++ /dev/null @@ -1,293 +0,0 @@ -/* ----------------------------------------------------------------------------- - * globalvar.i - * - * Global variables - add the variable to PHP - * ----------------------------------------------------------------------------- */ - -%typemap(varinit) char * -{ - zval z_var; - if ($1) { - ZVAL_STRING(&z_var, $1); - } else { - ZVAL_STR(&z_var, ZSTR_EMPTY_ALLOC()); - } - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) char [] -{ - zval z_var; - ZVAL_STRING(&z_var, $1); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) int, - unsigned int, - unsigned short, - short, - unsigned short, - long, - unsigned long, - signed char, - unsigned char, - enum SWIGTYPE -{ - zval z_var; - ZVAL_LONG(&z_var, (long)$1); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) bool -{ - zval z_var; - ZVAL_BOOL(&z_var, ($1)?1:0); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) float, double -{ - zval z_var; - ZVAL_DOUBLE(&z_var, (double)$1); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) char -{ - zval z_var; - char c = $1; - ZVAL_STRINGL(&z_var, &c, 1); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) SWIGTYPE *, SWIGTYPE [] -{ - zval z_var; - SWIG_SetPointerZval(&z_var, (void*)$1, $1_descriptor, 0); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) SWIGTYPE, SWIGTYPE &, SWIGTYPE && -{ - zval z_var; - SWIG_SetPointerZval(&z_var, (void*)&$1, $&1_descriptor, 0); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit) char [ANY] -{ - zval z_var; - /* varinit char [ANY] */ - ZVAL_STRINGL(&z_var, $1, $1_dim0); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); -} - -%typemap(varinit, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) -{ - zval resource; - void * p = emalloc(sizeof($1)); - memcpy(p, &$1, sizeof($1)); - ZVAL_RES(&resource, zend_register_resource(p, swig_member_ptr)); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &resource); -} - -%typemap(varin) int, unsigned int, short, unsigned short, long, unsigned long, signed char, unsigned char, enum SWIGTYPE -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - $1 = zval_get_long(z_var); -} - -%typemap(varin) bool -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - convert_to_boolean(z_var); - $1 = (Z_TYPE_P(z_var) == IS_TRUE); -} - -%typemap(varin) double,float -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - $1 = zval_get_double(z_var); -} - -%typemap(varin) char -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - convert_to_string(z_var); - if ($1 != Z_STRVAL_P(z_var)[0]) { - $1 = Z_STRVAL_P(z_var)[0]; - } -} - -%typemap(varin) char * -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - char *s1; - convert_to_string(z_var); - s1 = Z_STRVAL_P(z_var); - if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { - if (s1) - $1 = estrdup(s1); - else - $1 = NULL; - } -} - - -%typemap(varin) SWIGTYPE [] -{ - if ($1) { - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, $owner); - } -} - -%typemap(varin) char [ANY] -{ - zval **z_var; - char *s1; - - zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1, (void**)&z_var); - s1 = Z_STRVAL_P(z_var); - if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { - if (s1) - strncpy($1, s1, $1_dim0); - } -} - -%typemap(varin) SWIGTYPE -{ - zval *z_var; - $&1_ltype _temp; - - z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - if (SWIG_ConvertPtr(z_var, (void**)&_temp, $&1_descriptor, 0) < 0) { - SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); - } - - $1 = *($&1_ltype)_temp; -} - -%typemap(varin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && -{ - zval *z_var; - $1_ltype _temp; - - z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - if (SWIG_ConvertPtr(z_var, (void **)&_temp, $1_descriptor, 0) < 0) { - SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); - } - - $1 = ($1_ltype)_temp; -} - -%typemap(varin, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - void * p = (void*)zend_fetch_resource_ex(z_var, SWIG_MEMBER_PTR, swig_member_ptr); - memcpy(&$1, p, sizeof($1)); -} - -%typemap(varout) int, - unsigned int, - unsigned short, - short, - long, - unsigned long, - signed char, - unsigned char, - enum SWIGTYPE -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - if ($1 != ($1_ltype)Z_LVAL_P(z_var)) { - z_var->value.lval = (long)$1; - } -} - -//SAMFIX need to cast zval->type, what if zend-hash_find fails? etc? -%typemap(varout) bool -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - if ($1 != ($1_ltype)Z_LVAL_P(z_var)) { - z_var->value.lval = (long)$1; - } -} - -%typemap(varout) double, float -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - if ($1 != ($1_ltype)Z_DVAL_P(z_var)) { - z_var->value.dval = (double)$1; - } -} - -%typemap(varout) char -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - char c = $1; - if ($1 != Z_STRVAL_P(z_val)[0]) { - ZVAL_STRING(z_var, &c); - } -} - -%typemap(varout) char * -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - const char *s1 = Z_STRVAL_P(z_var); - if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { - if (s1) - efree(s1); - if ($1) { - (z_var)->value.str.val = estrdup($1); - (z_var)->value.str.len = strlen($1) + 1; - } else { - (z_var)->value.str.val = 0; - (z_var)->value.str.len = 0; - } - } -} - -%typemap(varout) SWIGTYPE -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - SWIG_SetPointerZval(z_var, (void*)&$1, $&1_descriptor, 0); -} - -%typemap(varout) SWIGTYPE [] -{ - if($1) { - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); - } -} - -%typemap(varout) char [ANY] -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - const char *s1 = Z_STRVAL_P(z_var); -deliberate error cos this code looks bogus to me - if ((s1 == NULL) || strcmp(s1, $1)) { - if ($1) { - (z_var)->value.str.val = estrdup($1); - (z_var)->value.str.len = strlen($1) + 1; - } else { - (z_var)->value.str.val = 0; - (z_var)->value.str.len = 0; - } - } -} - -%typemap(varout) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && -{ - zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); - SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); -} - -%typemap(varout, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) -{ - zval resource; - void * p = emalloc(sizeof($1)); - memcpy(p, &$1, sizeof($1)); - ZVAL_RES(&resource, zend_register_resource(p, swig_member_ptr)); - zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &resource); -} diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 4eba6be2a..ca8704fd8 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -4,13 +4,19 @@ * PHP configuration file * ----------------------------------------------------------------------------- */ +%include <typemaps/fragments.swg> + +// Default to generating PHP type declarations (for PHP >= 8) except for +// cases which are liable to cause compatibility issues with existing +// bindings. +%feature("php:type", "compat"); + %runtime "swigrun.swg" // Common C API type-checking code %runtime "swigerrors.swg" // SWIG errors %runtime "phprun.swg" // PHP runtime functions %include <phpinit.swg> // PHP initialization routine. -%include <globalvar.i> // Global variables. %include <const.i> // use %init %{ "/*code goes here*/ " %} @@ -35,107 +41,142 @@ %include <utils.i> -%pass_by_val(bool,CONVERT_BOOL_IN); +%pass_by_val(bool, "bool", CONVERT_BOOL_IN); -%pass_by_val(size_t, CONVERT_INT_IN); +%pass_by_val(size_t, "int", CONVERT_INT_IN); -%pass_by_val(enum SWIGTYPE, CONVERT_INT_IN); +%pass_by_val(enum SWIGTYPE, "int", CONVERT_INT_IN); -%pass_by_val(signed int, CONVERT_INT_IN); -%pass_by_val(int,CONVERT_INT_IN); -%pass_by_val(unsigned int,CONVERT_INT_IN); +%pass_by_val(signed int, "int", CONVERT_INT_IN); +%pass_by_val(int,"int", CONVERT_INT_IN); +%pass_by_val(unsigned int,"int", CONVERT_INT_IN); -%pass_by_val(signed short, CONVERT_INT_IN); -%pass_by_val(short,CONVERT_INT_IN); -%pass_by_val(unsigned short, CONVERT_INT_IN); +%pass_by_val(signed short, "int", CONVERT_INT_IN); +%pass_by_val(short,"int", CONVERT_INT_IN); +%pass_by_val(unsigned short, "int", CONVERT_INT_IN); -%pass_by_val(signed long, CONVERT_INT_IN); -%pass_by_val(long, CONVERT_INT_IN); -%pass_by_val(unsigned long, CONVERT_INT_IN); +%pass_by_val(signed long, "int", CONVERT_INT_IN); +%pass_by_val(long, "int", CONVERT_INT_IN); +%pass_by_val(unsigned long, "int", CONVERT_INT_IN); -%pass_by_val(signed long long, CONVERT_LONG_LONG_IN); -%pass_by_val(long long, CONVERT_LONG_LONG_IN); -%pass_by_val(unsigned long long, CONVERT_UNSIGNED_LONG_LONG_IN); +%pass_by_val(signed long long, "int|string", CONVERT_LONG_LONG_IN); +%pass_by_val(long long, "int|string", CONVERT_LONG_LONG_IN); +%pass_by_val(unsigned long long, "int|string", CONVERT_UNSIGNED_LONG_LONG_IN); -%pass_by_val(signed char, CONVERT_INT_IN); -%pass_by_val(char, CONVERT_CHAR_IN); -%pass_by_val(unsigned char, CONVERT_INT_IN); +%pass_by_val(signed char, "int", CONVERT_INT_IN); +%pass_by_val(char, "string", CONVERT_CHAR_IN); +%pass_by_val(unsigned char, "int", CONVERT_INT_IN); -%pass_by_val(float, CONVERT_FLOAT_IN); +%pass_by_val(float, "float", CONVERT_FLOAT_IN); -%pass_by_val(double, CONVERT_FLOAT_IN); +%pass_by_val(double, "float", CONVERT_FLOAT_IN); -%pass_by_val(char *, CONVERT_STRING_IN); +%pass_by_val(char *, "string", CONVERT_STRING_IN); %typemap(in) char *& = const char *&; %typemap(directorout) char *& = const char *&; // char array can be in/out, though the passed string may not be big enough... // so we have to size it -%typemap(in) char[ANY] +%typemap(in, phptype="string") char[ANY] %{ convert_to_string(&$input); $1 = ($1_ltype) Z_STRVAL($input); %} -%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) %{ +%typemap(in, phptype="string") (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) %{ convert_to_string(&$input); $1 = ($1_ltype) Z_STRVAL($input); $2 = ($2_ltype) Z_STRLEN($input); %} /* Object passed by value. Convert to a pointer */ -%typemap(in) SWIGTYPE ($&1_ltype tmp) +%typemap(in, phptype="SWIGTYPE") SWIGTYPE ($&1_ltype tmp) %{ - if (SWIG_ConvertPtr(&$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); - } - $1 = *tmp; + if (SWIG_ConvertPtr(&$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { + zend_type_error("Expected $&1_descriptor for argument $argnum of $symname"); + return; + } + $1 = *tmp; %} %typemap(directorout) SWIGTYPE ($&1_ltype tmp) %{ - /* If exit was via exception, PHP NULL is returned so skip the conversion. */ - if (!EG(exception)) { - if (SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); - $result = *tmp; - } + if (SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { + zend_type_error("Expected $&1_descriptor for argument $argnum of $symname"); + SWIG_fail; + } + $result = *tmp; %} -%typemap(in) SWIGTYPE *, +%typemap(in, phptype="?SWIGTYPE") SWIGTYPE *, SWIGTYPE [] %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); - } + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { + zend_type_error("Expected $1_descriptor for argument $argnum of $symname"); + return; + } %} -%typemap(in) SWIGTYPE & +%typemap(directorout) SWIGTYPE * (swig_owntype own), + SWIGTYPE [] (swig_owntype own) %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); - } + if (SWIG_ConvertPtrAndOwn($input, (void **)&$result, $1_descriptor, SWIG_POINTER_DISOWN, &own) < 0) { + zend_type_error("Expected $1_descriptor for argument $argnum of $symname"); + SWIG_fail; + } + swig_acquire_ownership_obj((void*)$result, own); %} -%typemap(in) SWIGTYPE && +%typemap(in, phptype="SWIGTYPE") SWIGTYPE & %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); - } + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { + zend_type_error("Expected $1_descriptor for argument $argnum of $symname"); + return; + } +%} +%typemap(in, fragment="<memory>") SWIGTYPE && (void *argp = 0, int res = 0, std::unique_ptr<$*1_ltype> rvrdeleter) %{ + res = SWIG_ConvertPtr(&$input, &argp, $descriptor, SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $1_descriptor of $symname"); + return; + } else { + zend_type_error("Expected $1_descriptor for argument $argnum of $symname"); + return; + } + } + if (!argp) { + zend_type_error("Invalid null reference for argument $argnum of $1_descriptor of $symname"); + return; + } + $1 = ($1_ltype)argp; + rvrdeleter.reset($1); +%} + +%typemap(directorout) SWIGTYPE & ($1_ltype tmp), + SWIGTYPE && ($1_ltype tmp) +%{ + if (SWIG_ConvertPtr($input, (void **) &tmp, $1_descriptor, 0) < 0 || tmp == NULL) { + zend_type_error("Expected $1_descriptor for argument $argnum of $symname"); + SWIG_fail; + } + $result = tmp; %} -%typemap(in) SWIGTYPE *const& ($*ltype temp) +%typemap(in, phptype="?SWIGTYPE") SWIGTYPE *const& ($*ltype temp) %{ - if (SWIG_ConvertPtr(&$input, (void **) &temp, $*1_descriptor, 0) < 0) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $*1_descriptor"); - } - $1 = ($1_ltype)&temp; + if (SWIG_ConvertPtr(&$input, (void **) &temp, $*1_descriptor, 0) < 0) { + zend_type_error("Expected $*1_descriptor for argument $argnum of $symname"); + return; + } + $1 = ($1_ltype)&temp; %} -%typemap(in) SWIGTYPE *DISOWN +%typemap(in, phptype="?SWIGTYPE") SWIGTYPE *DISOWN %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN) < 0) { + zend_type_error("Expected $1_descriptor for argument $argnum of $symname"); + return; } %} @@ -144,19 +185,22 @@ SWIGTYPE &, SWIGTYPE &&; -%typemap(in) void * +%typemap(in, phptype="?SWIGTYPE") void * %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, 0, 0) < 0) { - /* Allow NULL from php for void* */ - if (Z_ISNULL($input)) $1=0; - else - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); - } + if (SWIG_ConvertPtr(&$input, (void **) &$1, 0, 0) < 0) { + /* Allow NULL from php for void* */ + if (Z_ISNULL($input)) { + $1=0; + } else { + zend_type_error("Expected $1_descriptor for argument $argnum of $symname"); + return; + } + } %} /* Special case when void* is passed by reference so it can be made to point to opaque api structs */ -%typemap(in) void ** ($*1_ltype ptr, int force), +%typemap(in, phptype="?SWIG\\_p_void", byref=1) void ** ($*1_ltype ptr, int force), void *& ($*1_ltype ptr, int force) { /* If they pass NULL by reference, make it into a void* @@ -165,7 +209,8 @@ /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ if (!(Z_ISREF($input) && Z_ISNULL_P(Z_REFVAL($input)))) { /* wasn't a pre/ref/thing, OR anything like an int thing */ - SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); + zend_throw_exception(zend_ce_type_error, "Type error in argument $arg of $symname", 0); + goto fail; } } force=0; @@ -183,14 +228,15 @@ %typemap(argout) void **, void *& %{ - if (force$argnum) { - SWIG_SetPointerZval(&$input, (void*) ptr$argnum, $*1_descriptor, 1); + if (force$argnum && Z_ISREF($input)) { + SWIG_SetPointerZval(Z_REFVAL($input), (void*) ptr$argnum, $*1_descriptor, 1); } %} /* Typemap for output values */ -%typemap(out) int, +%typemap(out, phptype="int") + int, unsigned int, short, unsigned short, @@ -198,39 +244,35 @@ unsigned long, signed char, unsigned char, - bool, size_t %{ RETVAL_LONG($1); %} -%typemap(out) enum SWIGTYPE +%typemap(out, phptype="int") enum SWIGTYPE %{ RETVAL_LONG((long)$1); %} -%typemap(out) long long +%typemap(out, phptype="int|string") long long %{ if ((long long)LONG_MIN <= $1 && $1 <= (long long)LONG_MAX) { RETVAL_LONG((long)($1)); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)$1); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%lld", (long long)$1)); } %} -%typemap(out) unsigned long long +%typemap(out, phptype="int|string") unsigned long long %{ if ($1 <= (unsigned long long)LONG_MAX) { RETVAL_LONG((long)($1)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)$1); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%llu", (unsigned long long)$1)); } %} -%typemap(out) const int &, +%typemap(out, phptype="int") + const int &, const unsigned int &, const short &, const unsigned short &, @@ -244,34 +286,30 @@ RETVAL_LONG(*$1); %} -%typemap(out) const enum SWIGTYPE & +%typemap(out, phptype="int") const enum SWIGTYPE & %{ RETVAL_LONG((long)*$1); %} -%typemap(out) const enum SWIGTYPE && +%typemap(out, phptype="int") const enum SWIGTYPE && %{ RETVAL_LONG((long)*$1); %} -%typemap(out) const long long & +%typemap(out, phptype="int|string") const long long & %{ if ((long long)LONG_MIN <= *$1 && *$1 <= (long long)LONG_MAX) { RETVAL_LONG((long)(*$1)); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)(*$1)); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%lld", (long long)(*$1))); } %} -%typemap(out) const unsigned long long & +%typemap(out, phptype="int|string") const unsigned long long & %{ if (*$1 <= (unsigned long long)LONG_MAX) { RETVAL_LONG((long)(*$1)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)(*$1)); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%llu", (unsigned long long)(*$1))); } %} @@ -303,12 +341,12 @@ } %} -%typemap(out) bool +%typemap(out, phptype="bool") bool %{ RETVAL_BOOL(($1) ? 1 : 0); %} -%typemap(out) const bool & +%typemap(out, phptype="bool") const bool & %{ RETVAL_BOOL((*$1) ? 1 : 0); %} @@ -318,13 +356,13 @@ ZVAL_BOOL($input, ($1) ? 1 : 0); %} -%typemap(out) float, +%typemap(out, phptype="float") float, double %{ RETVAL_DOUBLE($1); %} -%typemap(out) const float &, +%typemap(out, phptype="float") const float &, const double & %{ RETVAL_DOUBLE(*$1); @@ -336,18 +374,22 @@ ZVAL_DOUBLE($input, $1); %} -%typemap(out) char +%typemap(out, phptype="string") char %{ RETVAL_STRINGL(&$1, 1); %} -%typemap(out) const char & +%typemap(out, phptype="string") const char & %{ RETVAL_STRINGL(&*$1, 1); %} -%typemap(out) char *, - char [] +%typemap(out, phptype="string") char [] +%{ + RETVAL_STRING((const char *)$1); +%} + +%typemap(out, phptype="?string") char * %{ if (!$1) { RETVAL_NULL(); @@ -356,7 +398,7 @@ } %} -%typemap(out) char *& +%typemap(out, phptype="?string") char *& %{ if (!*$1) { RETVAL_NULL(); @@ -365,17 +407,22 @@ } %} -%typemap(out) SWIGTYPE *, +%typemap(out, phptype="?SWIGTYPE") SWIGTYPE * +%{ + SWIG_SetPointerZval($result, (void *)$1, $1_descriptor, $owner); +%} + +%typemap(out, phptype="SWIGTYPE") SWIGTYPE [], SWIGTYPE &, SWIGTYPE && %{ - SWIG_SetPointerZval(return_value, (void *)$1, $1_descriptor, $owner); + SWIG_SetPointerZval($result, (void *)$1, $1_descriptor, $owner); %} -%typemap(out) SWIGTYPE *const& +%typemap(out, phptype="?SWIGTYPE") SWIGTYPE *const& %{ - SWIG_SetPointerZval(return_value, (void *)*$1, $*1_descriptor, $owner); + SWIG_SetPointerZval($result, (void *)*$1, $*1_descriptor, $owner); %} %typemap(directorin) SWIGTYPE *, @@ -383,53 +430,57 @@ SWIGTYPE &, SWIGTYPE && %{ - SWIG_SetPointerZval($input, (void *)&$1, $1_descriptor, ($owner)|2); + ZVAL_UNDEF($input); + SWIG_SetPointerZval($input, (void *)&$1, $1_descriptor, $owner); %} -%typemap(out, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) +%typemap(out, phptype="SWIGTYPE") SWIGTYPE (CLASS::*) { void * p = emalloc(sizeof($1)); memcpy(p, &$1, sizeof($1)); - RETVAL_RES(zend_register_resource(p, swig_member_ptr)); + SWIG_SetPointerZval($result, (void *)p, $&1_descriptor, 1); } -%typemap(in, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) +%typemap(in, phptype="SWIGTYPE") SWIGTYPE (CLASS::*) { - void * p = (void*)zend_fetch_resource_ex(&$input, SWIG_MEMBER_PTR, swig_member_ptr); + void * p = SWIG_Z_FETCH_OBJ_P(&$input)->ptr; memcpy(&$1, p, sizeof($1)); } -%typemap(out) SWIGTYPE *DYNAMIC, - SWIGTYPE &DYNAMIC +%typemap(out, phptype="?SWIGTYPE") SWIGTYPE *DYNAMIC { swig_type_info *ty = SWIG_TypeDynamicCast($1_descriptor, (void **) &$1); - SWIG_SetPointerZval(return_value, (void *)$1, ty, $owner); + SWIG_SetPointerZval($result, (void *)$1, ty, $owner); } -%typemap(out) SWIGTYPE -#ifdef __cplusplus +%typemap(out, phptype="SWIGTYPE") SWIGTYPE &DYNAMIC { - $&1_ltype resultobj = new $1_ltype((const $1_ltype &) $1); - SWIG_SetPointerZval(return_value, (void *)resultobj, $&1_descriptor, 1); + swig_type_info *ty = SWIG_TypeDynamicCast($1_descriptor, (void **) &$1); + SWIG_SetPointerZval($result, (void *)$1, ty, $owner); } -#else + +%typemap(out, phptype="SWIGTYPE") SWIGTYPE { - $&1_ltype resultobj = ($&1_ltype) emalloc(sizeof($1_type)); +#ifdef __cplusplus + $&1_ltype resultobj = new $1_ltype($1); +#else + $&1_ltype resultobj = ($&1_ltype) malloc(sizeof($1_type)); memcpy(resultobj, &$1, sizeof($1_type)); - SWIG_SetPointerZval(return_value, (void *)resultobj, $&1_descriptor, 1); -} #endif + SWIG_SetPointerZval($result, (void *)resultobj, $&1_descriptor, 1); +} %typemap(directorin) SWIGTYPE %{ - SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&1_descriptor, 1|2); + ZVAL_UNDEF($input); + SWIG_SetPointerZval($input, (new $1_ltype(SWIG_STD_MOVE($1))), $&1_descriptor, 1); %} -%typemap(out) void ""; +%typemap(out, phptype="void") void "" -%typemap(out) char [ANY] +%typemap(out, phptype="string") char [ANY] { - int len = 0; + size_t len = 0; while (len < $1_dim0 && $1[len]) ++len; RETVAL_STRINGL($1, len); } @@ -448,24 +499,38 @@ " $1 = (Z_TYPE($input) == is1 || Z_TYPE($input) == is2);" %enddef -%php_typecheck(int,SWIG_TYPECHECK_INTEGER,IS_LONG) -%php_typecheck(unsigned int,SWIG_TYPECHECK_UINT32,IS_LONG) -%php_typecheck(short,SWIG_TYPECHECK_INT16,IS_LONG) -%php_typecheck(unsigned short,SWIG_TYPECHECK_UINT16,IS_LONG) -%php_typecheck(long,SWIG_TYPECHECK_INT32,IS_LONG) -%php_typecheck(unsigned long,SWIG_TYPECHECK_UINT32,IS_LONG) -%php_typecheck(long long,SWIG_TYPECHECK_INT64,IS_LONG) -%php_typecheck(unsigned long long,SWIG_TYPECHECK_UINT64,IS_LONG) -%php_typecheck(signed char,SWIG_TYPECHECK_INT8,IS_LONG) -%php_typecheck(unsigned char,SWIG_TYPECHECK_UINT8,IS_LONG) -%php_typecheck(size_t,SWIG_TYPECHECK_SIZE,IS_LONG) +%define %php_typecheck_long(_type,_prec,_min,_max) +%typemap(typecheck,precedence=_prec) _type, const _type & %{ + $1 = (Z_TYPE($input) == IS_LONG && + (_min <= ZEND_LONG_MIN || (zend_long)_min <= Z_LVAL($input)) && + (_max >= ZEND_LONG_MAX || (zend_long)_max >= Z_LVAL($input))); +%} +%enddef + +%php_typecheck_long(int,SWIG_TYPECHECK_INTEGER,INT_MIN,INT_MAX) +%php_typecheck_long(unsigned int,SWIG_TYPECHECK_UINT32,0,UINT_MAX) +%php_typecheck_long(short,SWIG_TYPECHECK_INT16,SHRT_MIN,SHRT_MAX) +%php_typecheck_long(unsigned short,SWIG_TYPECHECK_UINT16,0,USHRT_MAX) +%php_typecheck_long(long,SWIG_TYPECHECK_INT32,LONG_MIN,LONG_MAX) +%php_typecheck_long(unsigned long,SWIG_TYPECHECK_UINT32,0,ULONG_MAX) +%php_typecheck_long(long long,SWIG_TYPECHECK_INT64,LLONG_MIN,LLONG_MAX) +%php_typecheck_long(unsigned long long,SWIG_TYPECHECK_UINT64,0,ULLONG_MAX) +%php_typecheck_long(signed char,SWIG_TYPECHECK_INT8,SCHAR_MIN,SCHAR_MAX) +%php_typecheck_long(unsigned char,SWIG_TYPECHECK_UINT8,0,UCHAR_MAX) +%php_typecheck_long(size_t,SWIG_TYPECHECK_SIZE,0,(size_t)-1) %php_typecheck(enum SWIGTYPE,SWIG_TYPECHECK_INTEGER,IS_LONG) %php_typecheck2(bool,SWIG_TYPECHECK_BOOL,IS_TRUE,IS_FALSE) -%php_typecheck(float,SWIG_TYPECHECK_FLOAT,IS_DOUBLE) +%typemap(typecheck,precedence=SWIG_TYPECHECK_FLOAT,fragment="SWIG_Float_Overflow_Check") float, const float & %{ + $1 = (Z_TYPE($input) == IS_DOUBLE && !SWIG_Float_Overflow_Check(Z_DVAL($input))); +%} +/* Don't range check here since PHP stores this as C/C++ double. */ %php_typecheck(double,SWIG_TYPECHECK_DOUBLE,IS_DOUBLE) %php_typecheck(char,SWIG_TYPECHECK_CHAR,IS_STRING) -%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) char *, char *&, char [] +%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) char *, char *& + " $1 = (Z_TYPE($input) == IS_STRING || Z_TYPE($input) == IS_NULL); " + +%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) char [] " $1 = (Z_TYPE($input) == IS_STRING); " %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE @@ -512,18 +577,18 @@ unsigned long, unsigned short %{ zend_throw_exception(NULL, "C++ $1_type exception thrown", $1); - return; + goto fail; %} %typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY] %{ (void)$1; zend_throw_exception(NULL, "C++ $1_type exception thrown", 0); - return; + goto fail; %} %typemap(throws) char * %{ zend_throw_exception(NULL, $1, 0); - return; + goto fail; %} /* Array reference typemaps */ @@ -537,3 +602,6 @@ /* php keywords */ %include <phpkw.swg> + +/* PHP known interfaces */ +%include <phpinterfaces.i> diff --git a/Lib/php/phpinit.swg b/Lib/php/phpinit.swg index 1665f5dc4..ae72a10ae 100644 --- a/Lib/php/phpinit.swg +++ b/Lib/php/phpinit.swg @@ -7,19 +7,10 @@ %init %{ SWIG_php_minit { + zend_class_entry SWIGUNUSED internal_ce; SWIG_InitializeModule((void*)&module_number); -%} - -%fragment("swig_php_init_member_ptr2", "header") %{ -#define SWIG_MEMBER_PTR "CLASS::*" - -static void swig_member_ptr_dtor(zend_resource *res) { - efree(res->ptr); -} - -static int swig_member_ptr = 0; -%} - -%fragment("swig_php_init_member_ptr", "init", fragment="swig_php_init_member_ptr2") %{ - swig_member_ptr = zend_register_list_destructors_ex(swig_member_ptr_dtor, NULL, SWIG_MEMBER_PTR, module_number); +#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION == 0 + /* This hack is needed to avoid segfaults. */ + EG(class_table) = CG(class_table); +#endif %} diff --git a/Lib/php/phpinterfaces.i b/Lib/php/phpinterfaces.i new file mode 100644 index 000000000..e1029b645 --- /dev/null +++ b/Lib/php/phpinterfaces.i @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------- + * phpinterfaces.i + * + * Define "known" PHP interfaces. + * + * These can be added at MINIT time (which is when PHP loads the extension + * module). + * + * Any interface can be added via phpinterfaces, but looking up the + * zend_class_entry by name has to wait until RINIT time, which means it + * happens for every request. + * ----------------------------------------------------------------------------- */ + +// Note: Abstract interfaces such as "Traversable" can't be used in +// "implements" so are not relevant here. + +%insert(header) %{ + +#define SWIG_PHP_INTERFACE_Iterator_CE zend_ce_iterator +#define SWIG_PHP_INTERFACE_Iterator_HEADER "zend_interfaces.h" + +#define SWIG_PHP_INTERFACE_IteratorAggregate_CE zend_ce_aggregate +#define SWIG_PHP_INTERFACE_IteratorAggregate_HEADER "zend_interfaces.h" + +#define SWIG_PHP_INTERFACE_ArrayAccess_CE zend_ce_arrayaccess +#define SWIG_PHP_INTERFACE_ArrayAccess_HEADER "zend_interfaces.h" + +#define SWIG_PHP_INTERFACE_Serializable_CE zend_ce_serializable +#define SWIG_PHP_INTERFACE_Serializable_HEADER "zend_interfaces.h" + +#define SWIG_PHP_INTERFACE_Countable_CE zend_ce_countable +#define SWIG_PHP_INTERFACE_Countable_HEADER "zend_interfaces.h" + +#define SWIG_PHP_INTERFACE_OuterIterator_CE spl_ce_OuterIterator +#define SWIG_PHP_INTERFACE_OuterIterator_HEADER "ext/spl/spl_iterators.h" + +#define SWIG_PHP_INTERFACE_RecursiveIterator_CE spl_ce_RecursiveIterator +#define SWIG_PHP_INTERFACE_RecursiveIterator_HEADER "ext/spl/spl_iterators.h" + +#define SWIG_PHP_INTERFACE_SeekableIterator_CE spl_ce_SeekableIterator +#define SWIG_PHP_INTERFACE_SeekableIterator_HEADER "ext/spl/spl_iterators.h" + +#define SWIG_PHP_INTERFACE_SplObserver_CE spl_ce_SplObserver +#define SWIG_PHP_INTERFACE_SplObserver_HEADER "ext/spl/spl_observer.h" + +#define SWIG_PHP_INTERFACE_SplSubject_CE spl_ce_SplSubject +#define SWIG_PHP_INTERFACE_SplSubject_HEADER "ext/spl/spl_observer.h" + +#define SWIG_PHP_INTERFACE_DateTimeInterface_CE php_date_get_interface_ce() +#define SWIG_PHP_INTERFACE_DateTimeInterface_HEADER "ext/date/php_date.h" + +// The "json" extension needs to be loaded earlier that us for this to work. +#define SWIG_PHP_INTERFACE_JsonSerializable_CE php_json_serializable_ce +#define SWIG_PHP_INTERFACE_JsonSerializable_HEADER "ext/json/php_json.h" + +// New in PHP 8.0. +#define SWIG_PHP_INTERFACE_Stringable_CE zend_ce_stringable +#define SWIG_PHP_INTERFACE_Stringable_HEADER "zend_interfaces.h" + +%} diff --git a/Lib/php/phpkw.swg b/Lib/php/phpkw.swg index 5c5296a1f..443ac8bf8 100644 --- a/Lib/php/phpkw.swg +++ b/Lib/php/phpkw.swg @@ -3,10 +3,13 @@ * ----------------------------------------------------------------------------- */ /* Keyword (case insensitive) */ -#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renaming to 'c_" `x` "'",sourcefmt="%(lower)s",rename="c_%s") `x` +#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword",sourcefmt="%(lower)s",rename="c_%s") `x` + +/* Keyword, except ok as a function */ +#define PHPKW_ok_as_function(x) %keywordwarn("'" `x` "' is a PHP keyword, renaming to 'c_" `x` "'",%$not %$isfunction,sourcefmt="%(lower)s",rename="c_%s") `x` /* Class (case insensitive) */ -#define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name, renaming to 'c_" `x` "'",%$isclass,sourcefmt="%(lower)s",rename="c_%s") `x` +#define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name",%$isclass,sourcefmt="%(lower)s",rename="c_%s") `x` /* Constant (case insensitive) */ #define PHPBN1a(x) %namewarn(%warningmsg(SWIGWARN_PARSE_BUILTIN_NAME, "enum conflicts with a built-in constant '"`x`"' in PHP"),%$isenumitem,sourcefmt="%(lower)s") `x` @@ -22,7 +25,7 @@ PHPBN2a(X); PHPBN2b(X) %enddef -#define PHPFN(x) %keywordwarn("'" `x` "' is a PHP built-in function, renaming to 'c_" `x` "'",sourcefmt="%(lower)s",%$isfunction,%$not %$ismember,rename="c_%s") `x` +#define PHPFN(x) %keywordwarn("'" `x` "' is a PHP built-in function",sourcefmt="%(lower)s",%$isfunction,%$not %$ismember,rename="c_%s") `x` /* From: http://php.net/manual/en/reserved.keywords.php * "You cannot use any of the following words as constants, class names, @@ -55,6 +58,7 @@ PHPKW(endwhile); PHPKW(extends); PHPKW(final); PHPKW(finally); +PHPKW(fn); // as of PHP 7.4 PHPKW(for); PHPKW(foreach); PHPKW(function); @@ -65,6 +69,7 @@ PHPKW(implements); PHPKW(instanceof); PHPKW(insteadof); PHPKW(interface); +PHPKW(match); // as of PHP 8.0 PHPKW(namespace); PHPKW(new); PHPKW(or); @@ -82,6 +87,11 @@ PHPKW(while); PHPKW(xor); PHPKW(yield); +/* PHP 8.1 made `readonly` a keyword, but (unlike any other keyword it seems) + * it may still be used as a function name. + */ +PHPKW_ok_as_function(readonly); + // Compile-time "magic" constants // From: http://php.net/manual/en/reserved.keywords.php // also at: http://php.net/manual/en/language.constants.predefined.php @@ -119,6 +129,10 @@ PHPBN2(PHP_SAPI); PHPBN2(PHP_EOL); PHPBN2(PHP_INT_MAX); PHPBN2(PHP_INT_SIZE); +PHPBN2(PHP_FLOAT_DIG); // Since 7.2.0 +PHPBN2(PHP_FLOAT_EPSILON); // Since 7.2.0 +PHPBN2(PHP_FLOAT_MIN); // Since 7.2.0 +PHPBN2(PHP_FLOAT_MAX); // Since 7.2.0 PHPBN2(DEFAULT_INCLUDE_PATH); PHPBN2(PEAR_INSTALL_DIR); PHPBN2(PEAR_EXTENSION_DIR); @@ -134,6 +148,7 @@ PHPBN2(PHP_LOCALSTATEDIR); PHPBN2(PHP_CONFIG_FILE_PATH); PHPBN2(PHP_CONFIG_FILE_SCAN_DIR); PHPBN2(PHP_SHLIB_SUFFIX); +PHPBN2(PHP_FD_SETSIZE); // Since 7.1.0 PHPBN2(E_ERROR); PHPBN2(E_WARNING); PHPBN2(E_PARSE); @@ -145,6 +160,7 @@ PHPBN2(E_COMPILE_WARNING); PHPBN2(E_USER_ERROR); PHPBN2(E_USER_WARNING); PHPBN2(E_USER_NOTICE); +PHPBN2(E_RECOVERABLE_ERROR); PHPBN2(E_DEPRECATED); PHPBN2(E_USER_DEPRECATED); PHPBN2(E_ALL); @@ -156,6 +172,9 @@ PHPBN2(__COMPILER_HALT_OFFSET__); PHPBN2(PHP_OUTPUT_HANDLER_START); PHPBN2(PHP_OUTPUT_HANDLER_CONT); PHPBN2(PHP_OUTPUT_HANDLER_END); +/* Since 7.4.0 (Microsoft Windows only) */ +PHPBN2(PHP_WINDOWS_EVENT_CTRL_C); +PHPBN2(PHP_WINDOWS_EVENT_CTRL_BREAK); /* These don't actually seem to be set (tested on Linux, I guess they're * Windows only?) */ PHPBN2(PHP_WINDOWS_NT_DOMAIN_CONTROLLER); @@ -402,21 +421,6 @@ PHPBN2(CURLOPT_TCP_NODELAY); PHPBN2(CURLOPT_TIMEOUT_MS); PHPBN2(CURLOPT_CONNECTTIMEOUT_MS); PHPBN2(GMP_VERSION); -PHPBN2(SWFTEXTFIELD_USEFONT); -PHPBN2(SWFTEXTFIELD_AUTOSIZE); -PHPBN2(SWF_SOUND_NOT_COMPRESSED); -PHPBN2(SWF_SOUND_ADPCM_COMPRESSED); -PHPBN2(SWF_SOUND_MP3_COMPRESSED); -PHPBN2(SWF_SOUND_NOT_COMPRESSED_LE); -PHPBN2(SWF_SOUND_NELLY_COMPRESSED); -PHPBN2(SWF_SOUND_5KHZ); -PHPBN2(SWF_SOUND_11KHZ); -PHPBN2(SWF_SOUND_22KHZ); -PHPBN2(SWF_SOUND_44KHZ); -PHPBN2(SWF_SOUND_8BITS); -PHPBN2(SWF_SOUND_16BITS); -PHPBN2(SWF_SOUND_MONO); -PHPBN2(SWF_SOUND_STEREO); PHPBN2(OPENSSL_VERSION_NUMBER); PHPBN2(SNMP_OID_OUTPUT_FULL); PHPBN2(SNMP_OID_OUTPUT_NUMERIC); @@ -627,27 +631,26 @@ PHPBN2(PGSQL_POLLING_OK); PHPBN2(PGSQL_POLLING_READING); PHPBN2(PGSQL_POLLING_WRITING); -/* Class names reserved by PHP (case insensitive) */ +/* Class names reserved by PHP. */ +/* Check is case insensitive - these *MUST* be listed in lower case here. */ PHPCN(directory); PHPCN(stdclass); PHPCN(__php_incomplete_class); -/* Added in PHP5. */ PHPCN(exception); PHPCN(errorexception); PHPCN(php_user_filter); PHPCN(closure); PHPCN(generator); PHPCN(self); -PHPCN(static); PHPCN(parent); /* http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.classes */ PHPCN(bool); // As of PHP 7.0 PHPCN(int); // As of PHP 7.0 PHPCN(float); // As of PHP 7.0 PHPCN(string); // As of PHP 7.0 -PHPCN(NULL); // As of PHP 7.0 -PHPCN(TRUE); // As of PHP 7.0 -PHPCN(FALSE); // As of PHP 7.0 +PHPCN(null); // As of PHP 7.0 +PHPCN(true); // As of PHP 7.0 +PHPCN(false); // As of PHP 7.0 PHPCN(resource); // As of PHP 7.0 (currently works but reserved) PHPCN(object); // As of PHP 7.0 (currently works but reserved) PHPCN(mixed); // As of PHP 7.0 (currently works but reserved) @@ -655,6 +658,14 @@ PHPCN(numeric); // As of PHP 7.0 (currently works but reserved) /* http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.invalid-class-names */ PHPCN(iterable); // As of PHP 7.1 PHPCN(void); // As of PHP 7.1 +/* Predefined interfaces and classes, introduced in PHP 7.0.0 */ +PHPCN(arithmeticerror); +PHPCN(assertionerror); +PHPCN(divisionbyzeroerror); +PHPCN(error); +PHPCN(throwable); +PHPCN(parseerror); +PHPCN(typeerror); /* From extensions (which of these are actually predefined depends which * extensions are loaded by default). */ PHPCN(xmlwriter); @@ -866,6 +877,7 @@ PHPFN(unset); // "Language construct" PHPFN(usort); #undef PHPKW +#undef PHPKW_ok_as_function #undef PHPBN1a #undef PHPBN1b #undef PHPBN1 diff --git a/Lib/php/phppointers.i b/Lib/php/phppointers.i index d79697b5e..a4ff3c0bd 100644 --- a/Lib/php/phppointers.i +++ b/Lib/php/phppointers.i @@ -1,16 +1,12 @@ -%define %pass_by_ref( TYPE, CONVERT_IN, CONVERT_OUT ) -%typemap(in, byref=1) TYPE *REF ($*1_ltype tmp), +%define %pass_by_ref( TYPE, PHP_TYPE, CONVERT_IN, CONVERT_OUT ) +%typemap(in,byref=1,phptype=PHP_TYPE) TYPE *REF ($*1_ltype tmp), TYPE &REF ($*1_ltype tmp) %{ - /* First Check for SWIG wrapped type */ - if (Z_ISNULL($input)) { - $1 = 0; - } else if (Z_ISREF($input)) { - /* Not swig wrapped type, so we check if it's a PHP reference type */ - CONVERT_IN(tmp, $*1_ltype, $input); - $1 = &tmp; + if (Z_ISREF($input)) { + CONVERT_IN(tmp, $*1_ltype, $input); + $1 = &tmp; } else { - SWIG_PHP_Error(E_ERROR, SWIG_PHP_Arg_Error_Msg($argnum, Expected a reference)); + zend_type_error(SWIG_PHP_Arg_Error_Msg($argnum, Expected a reference)); } %} %typemap(argout) TYPE *REF, @@ -22,25 +18,25 @@ %} %enddef -%pass_by_ref( size_t, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( size_t, "int", CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( signed int, CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( int, CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( unsigned int, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( signed int, "int", CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( int, "int", CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( unsigned int, "int", CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( signed short, CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( short, CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( unsigned short, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( signed short, "int", CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( short, "int", CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( unsigned short, "int", CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( signed long, CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( long, CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( unsigned long, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( signed long, "int", CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( long, "int", CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( unsigned long, "int", CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( signed char, CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( char, CONVERT_CHAR_IN, ZVAL_STRING ); -%pass_by_ref( unsigned char, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( signed char, "int", CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( char, "string", CONVERT_CHAR_IN, ZVAL_STRING ); +%pass_by_ref( unsigned char, "int", CONVERT_INT_IN, ZVAL_LONG ); -%pass_by_ref( float, CONVERT_FLOAT_IN, ZVAL_DOUBLE ); -%pass_by_ref( double, CONVERT_FLOAT_IN, ZVAL_DOUBLE ); +%pass_by_ref( float, "float", CONVERT_FLOAT_IN, ZVAL_DOUBLE ); +%pass_by_ref( double, "float", CONVERT_FLOAT_IN, ZVAL_DOUBLE ); -%pass_by_ref( char *, CONVERT_CHAR_IN, ZVAL_STRING ); +%pass_by_ref( char *, "string", CONVERT_CHAR_IN, ZVAL_STRING ); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index a07a1b9f8..588701f9b 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -4,24 +4,21 @@ * PHP runtime library * ----------------------------------------------------------------------------- */ +#define swig_owntype int + #ifdef __cplusplus extern "C" { #endif -#include "zend.h" -#include "zend_API.h" -#include "zend_exceptions.h" -#include "php.h" -#if PHP_MAJOR_VERSION != 7 -# error These bindings need PHP7 - to generate PHP5 bindings use: SWIG < 4.0.0 and swig -php5 +#if PHP_MAJOR_VERSION < 8 +# error These bindings need PHP 8 or later - to generate PHP7 bindings use SWIG < 4.1.0; to generate PHP5 bindings use: SWIG < 4.0.0 and swig -php5 #endif -#include "ext/standard/php_string.h" -#include <stdlib.h> /* for abort(), used in generated code. */ +#include "zend_inheritance.h" +#include "zend_exceptions.h" +#include "zend_inheritance.h" -/* This indirection is to work around const correctness issues in older PHP. - * FIXME: Remove for PHP7? Or might user code be using it? */ -#define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A) +#include <stdlib.h> /* for abort(), used in generated code. */ #define SWIG_BOOL_CONSTANT(N, V) REGISTER_BOOL_CONSTANT(#N, V, CONST_CS | CONST_PERSISTENT) #define SWIG_LONG_CONSTANT(N, V) REGISTER_LONG_CONSTANT(#N, V, CONST_CS | CONST_PERSISTENT) @@ -32,13 +29,6 @@ extern "C" { REGISTER_STRINGL_CONSTANT(#N, &swig_char, 1, CONST_CS | CONST_PERSISTENT);\ } while (0) -/* ZEND_CONSTANT_SET_FLAGS is new in PHP 7.3. */ -#ifdef ZEND_CONSTANT_SET_FLAGS -# define SWIG_ZEND_CONSTANT_SET_FLAGS ZEND_CONSTANT_SET_FLAGS -#else -# define SWIG_ZEND_CONSTANT_SET_FLAGS(C, F, N) do { (C)->flags = (F); (C)->module_number = (N); } while (0) -#endif - #ifdef __cplusplus } #endif @@ -50,178 +40,125 @@ static int default_error_code = E_ERROR; #define SWIG_PHP_Arg_Error_Msg(argnum,extramsg) "Error in argument " #argnum " "#extramsg -#define SWIG_PHP_Error(code,msg) do { SWIG_ErrorCode() = code; SWIG_ErrorMsg() = msg; SWIG_fail; } while (0) +#define SWIG_PHP_Error(code,msg) do { zend_throw_exception(NULL, msg, code); SWIG_fail; } while (0) #define SWIG_contract_assert(expr,msg) \ - if (!(expr) ) { zend_printf("Contract Assert Failed %s\n",msg ); } else + do { if (!(expr)) zend_printf("Contract Assert Failed %s\n", msg); } while (0) /* Standard SWIG API */ #define SWIG_GetModule(clientdata) SWIG_Php_GetModule() #define SWIG_SetModule(clientdata, pointer) SWIG_Php_SetModule(pointer, *(int*)clientdata) +static zend_class_entry SWIG_Php_swig_wrapped_interface_ce; + /* used to wrap returned objects in so we know whether they are newobject and need freeing, or not */ typedef struct { void * ptr; int newobject; + const swig_type_info * type; + zend_object std; } swig_object_wrapper; +#define SWIG_Z_FETCH_OBJ_P(zv) swig_php_fetch_object(Z_OBJ_P(zv)) + +static inline +swig_object_wrapper * swig_php_fetch_object(zend_object *obj) { + return (swig_object_wrapper *)((char *)obj - XtOffsetOf(swig_object_wrapper, std)); +} + #define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) static void SWIG_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject) { - /* - * First test for Null pointers. Return those as PHP native NULL - */ - if (!ptr ) { + // Return PHP NULL for a C/C++ NULL pointer. + if (!ptr) { ZVAL_NULL(z); return; } - if (type->clientdata) { - swig_object_wrapper *value; - if (! (*(int *)(type->clientdata))) - zend_error(E_ERROR, "Type: %s failed to register with zend",type->name); - value=(swig_object_wrapper *)emalloc(sizeof(swig_object_wrapper)); - value->ptr=ptr; - value->newobject=(newobject & 1); - if ((newobject & 2) == 0) { - /* Just register the pointer as a resource. */ - ZVAL_RES(z, zend_register_resource(value, *(int *)(type->clientdata))); - } else { - /* - * Wrap the resource in an object, the resource will be accessible - * via the "_cPtr" member. This is currently only used by - * directorin typemaps. - */ - zval resource; - zend_class_entry *ce = NULL; - const char *type_name = type->name+3; /* +3 so: _p_Foo -> Foo */ - size_t type_name_len; - const char * p; - HashTable * ht; - - /* Namespace__Foo -> Foo */ - /* FIXME: ugly and goes wrong for classes with __ in their names. */ - while ((p = strstr(type_name, "__")) != NULL) { - type_name = p + 2; - } - type_name_len = strlen(type_name); - - ZVAL_RES(&resource, zend_register_resource(value, *(int *)(type->clientdata))); - if (SWIG_PREFIX_LEN > 0) { - zend_string * classname = zend_string_alloc(SWIG_PREFIX_LEN + type_name_len, 0); - memcpy(classname->val, SWIG_PREFIX, SWIG_PREFIX_LEN); - memcpy(classname->val + SWIG_PREFIX_LEN, type_name, type_name_len); - ce = zend_lookup_class(classname); - zend_string_release(classname); - } else { - zend_string * classname = zend_string_init(type_name, type_name_len, 0); - ce = zend_lookup_class(classname); - zend_string_release(classname); - } - if (ce == NULL) { - /* class does not exist */ - ce = zend_standard_class_def; - } - ALLOC_HASHTABLE(ht); - zend_hash_init(ht, 1, NULL, NULL, 0); - zend_hash_str_update(ht, "_cPtr", sizeof("_cPtr") - 1, &resource); - object_and_properties_init(z, ce, ht); - } + if (!type->clientdata) { + zend_type_error("Type: %s not registered with zend", type->name); return; } - zend_error(E_ERROR, "Type: %s not registered with zend",type->name); -} - -/* This pointer conversion routine takes the native pointer p (along with - its type name) and converts it by calling appropriate casting functions - according to ty. The resultant pointer is returned, or NULL is returned - if the pointer can't be cast. - - Sadly PHP has no API to find a type name from a type id, only from an - instance of a resource of the type id, so we have to pass type_name as well. - - The two functions which might call this are: - SWIG_ConvertResourcePtr which gets the type name from the resource - and the registered zend destructors for which we have one per type each - with the type name hard wired in. */ -static void * -SWIG_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty) { - swig_cast_info *tc; - void *result = 0; - - if (!ty) { - /* They don't care about the target type, so just pass on the pointer! */ - return p; - } - - if (! type_name) { - /* can't convert p to ptr type ty if we don't know what type p is */ - return NULL; - } - - /* convert and cast p from type_name to ptr as ty. */ - tc = SWIG_TypeCheck(type_name, ty); - if (tc) { - int newmemory = 0; - result = SWIG_TypeCast(tc, p, &newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } - return result; -} -/* This function returns a pointer of type ty by extracting the pointer - and type info from the resource in z. z must be a resource. - If it fails, NULL is returned. - It uses SWIG_ConvertResourceData to do the real work. */ -static void * -SWIG_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags) { - swig_object_wrapper *value; - void *p; - const char *type_name; - - if (Z_RES_TYPE_P(z) == -1) return NULL; - value = (swig_object_wrapper *) Z_RES_VAL_P(z); - if (flags & SWIG_POINTER_DISOWN) { - value->newobject = 0; + { + zend_object *obj; + swig_object_wrapper *value; + if (Z_TYPE_P(z) == IS_OBJECT) { + /* The PHP object is already initialised - this is the case when wrapping + * the return value from a PHP constructor. */ + obj = Z_OBJ_P(z); + } else { + zend_class_entry *ce = (zend_class_entry*)(type->clientdata); + obj = ce->create_object(ce); + ZVAL_OBJ(z, obj); + } + value = swig_php_fetch_object(obj); + value->ptr = ptr; + value->newobject = (newobject & 1); + value->type = type; } - p = value->ptr; - - type_name=zend_rsrc_list_get_rsrc_type(Z_RES_P(z)); - - return SWIG_ConvertResourceData(p, type_name, ty); } -/* We allow passing of a RESOURCE pointing to the object or an OBJECT whose - _cPtr is a resource pointing to the object */ +/* We wrap C/C++ pointers as PHP objects. */ static int -SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) { +SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_owntype *own) { + if (own) + *own = 0; + if (z == NULL) { *ptr = 0; - return 0; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } switch (Z_TYPE_P(z)) { case IS_OBJECT: { - HashTable * ht = Z_OBJ_HT_P(z)->get_properties(z); - if (ht) { - zval * _cPtr = zend_hash_str_find(ht, "_cPtr", sizeof("_cPtr") - 1); - if (_cPtr) { - if (Z_TYPE_P(_cPtr) == IS_INDIRECT) { - _cPtr = Z_INDIRECT_P(_cPtr); - } - if (Z_TYPE_P(_cPtr) == IS_RESOURCE) { - *ptr = SWIG_ConvertResourcePtr(_cPtr, ty, flags); - return (*ptr == NULL ? -1 : 0); - } + zend_object *obj = Z_OBJ_P(z); + swig_object_wrapper *value; + if (ty && ty->clientdata == (void*)obj->ce) { + // Object is exactly the class asked for - this handles common cases cheaply, + // and in particular the PHP classes we use to wrap a pointer to a non-class. + } else if (!zend_class_implements_interface(obj->ce, &SWIG_Php_swig_wrapped_interface_ce)) { + // Not an object we've wrapped. + return -1; + } + + /* convert and cast value->ptr from value->type to ptr as ty. */ + value = swig_php_fetch_object(obj); + if (!ty) { + /* They don't care about the target type, so just pass on the pointer! */ + *ptr = value->ptr; + } else { + swig_cast_info *tc = SWIG_TypeCheck(value->type->name, ty); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc, value->ptr, &newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own |= SWIG_CAST_NEW_MEMORY; + } + } else { + *ptr = NULL; + } + } + + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !value->newobject) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (*ptr == NULL) + return SWIG_ERROR; /* should be SWIG_NullReferenceError?? */ + if (flags & SWIG_POINTER_DISOWN) { + value->newobject = 0; + } + if (flags & SWIG_POINTER_CLEAR) { + value->ptr = 0; } } - break; + + return SWIG_OK; } - case IS_RESOURCE: - *ptr = SWIG_ConvertResourcePtr(z, ty, flags); - return (*ptr == NULL ? -1 : 0); case IS_NULL: *ptr = 0; return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; @@ -230,17 +167,43 @@ SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) { return -1; } +static int +SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) { + return SWIG_ConvertPtrAndOwn(z, ptr, ty, flags, 0); +} + static const char const_name[] = "swig_runtime_data_type_pointer"; -static swig_module_info *SWIG_Php_GetModule() { +static swig_module_info *SWIG_Php_GetModule(void) { zval *pointer = zend_get_constant_str(const_name, sizeof(const_name) - 1); if (pointer) { if (Z_TYPE_P(pointer) == IS_LONG) { return (swig_module_info *) pointer->value.lval; } - } + } return NULL; } static void SWIG_Php_SetModule(swig_module_info *pointer, int module_number) { REGISTER_LONG_CONSTANT(const_name, (long) pointer, CONST_CS | CONST_PERSISTENT); } + +/* Common parts of the "create_object" object handler. */ +static zend_object *SWIG_Php_do_create_object(zend_class_entry *ce, zend_object_handlers *handlers) { + swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce); + zend_object_std_init(&obj->std, ce); + object_properties_init(&obj->std, ce); + obj->std.handlers = handlers; + obj->newobject = 1; + return &obj->std; +} + +/* Common parts of the "free_obj" object handler. + Returns void* pointer if the C/C++ object should be destroyed. */ +static void* SWIG_Php_free_obj(zend_object *object) { + if (object) { + swig_object_wrapper *obj = swig_php_fetch_object(object); + zend_object_std_dtor(&obj->std); + if (obj->newobject) return obj->ptr; + } + return NULL; +} diff --git a/Lib/php/std_auto_ptr.i b/Lib/php/std_auto_ptr.i new file mode 100644 index 000000000..284091657 --- /dev/null +++ b/Lib/php/std_auto_ptr.i @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %auto_ptr(TYPE) +%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $descriptor(TYPE *) of $symname"); + return; + } else { + zend_type_error("Expected $descriptor(TYPE *) for argument $argnum of $symname"); + return; + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); +%} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr(&$input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template <class T> class auto_ptr {}; +} diff --git a/Lib/php/std_common.i b/Lib/php/std_common.i index 092bf012b..1b69fc779 100644 --- a/Lib/php/std_common.i +++ b/Lib/php/std_common.i @@ -7,4 +7,3 @@ %include <std/std_except.i> %apply size_t { std::size_t }; - diff --git a/Lib/php/std_map.i b/Lib/php/std_map.i index 7c0157353..6904efc6e 100644 --- a/Lib/php/std_map.i +++ b/Lib/php/std_map.i @@ -35,7 +35,7 @@ namespace std { map(); map(const map& other); - + unsigned int size() const; void clear(); %extend { @@ -47,7 +47,11 @@ namespace std { throw std::out_of_range("key not found"); } void set(const K& key, const T& x) { +%#ifdef __cpp_lib_map_try_emplace + (*self).insert_or_assign(key, x); +%#else (*self)[key] = x; +%#endif } void del(const K& key) throw (std::out_of_range) { std::map< K, T, C >::iterator i = self->find(key); @@ -66,17 +70,4 @@ namespace std { } }; -// Legacy macros (deprecated) -%define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) -#warning "specialize_std_map_on_key ignored - macro is deprecated and no longer necessary" -%enddef - -%define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) -#warning "specialize_std_map_on_value ignored - macro is deprecated and no longer necessary" -%enddef - -%define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) -#warning "specialize_std_map_on_both ignored - macro is deprecated and no longer necessary" -%enddef - } diff --git a/Lib/php/std_string.i b/Lib/php/std_string.i index b55751f07..5abbbbbef 100644 --- a/Lib/php/std_string.i +++ b/Lib/php/std_string.i @@ -4,19 +4,21 @@ * SWIG typemaps for std::string types * ----------------------------------------------------------------------------- */ -// ------------------------------------------------------------------------ -// std::string is typemapped by value -// This can prevent exporting methods which return a string -// in order for the user to modify it. -// However, I think I'll wait until someone asks for it... -// ------------------------------------------------------------------------ - -%include <exception.i> - %{ #include <string> %} +/* std::string and const std::string& are converted to/from PHP string + * automatically. + * + * A C++ std::string& parameter is wrapped as a pass-by-reference PHP + * string parameter by default, but the INPUT/INOUT/OUTPUT typemaps + * below provide other options (see below). + * + * std::string* is not wrapped by default, but INPUT/INOUT/OUTPUT typemaps + * are provided (see below). + */ + namespace std { %naturalvar string; @@ -27,19 +29,17 @@ namespace std { $1 = (Z_TYPE($input) == IS_STRING) ? 1 : 0; %} - %typemap(in) string %{ + %typemap(in, phptype="string") string %{ convert_to_string(&$input); $1.assign(Z_STRVAL($input), Z_STRLEN($input)); %} %typemap(directorout) string %{ - if (!EG(exception)) { convert_to_string($input); $result.assign(Z_STRVAL_P($input), Z_STRLEN_P($input)); - } %} - %typemap(out) string %{ + %typemap(out, phptype="string") string %{ ZVAL_STRINGL($result, $1.data(), $1.size()); %} @@ -47,24 +47,31 @@ namespace std { ZVAL_STRINGL($input, $1.data(), $1.size()); %} - %typemap(out) const string & %{ + %typemap(out, phptype="string") const string& %{ ZVAL_STRINGL($result, $1->data(), $1->size()); %} %typemap(throws) string, const string& %{ zend_throw_exception(NULL, $1.c_str(), 0); - return; + goto fail; %} - %typemap(in) const string & ($*1_ltype temp) %{ + %typemap(throws) string*, const string* %{ + zend_throw_exception(NULL, $1->c_str(), 0); + goto fail; + %} + + %typemap(in, phptype="string") const string& ($*1_ltype temp) %{ convert_to_string(&$input); temp.assign(Z_STRVAL($input), Z_STRLEN($input)); $1 = &temp; %} - /* These next two handle a function which takes a non-const reference to - * a std::string and modifies the string. */ - %typemap(in,byref=1) string & ($*1_ltype temp) %{ + /*************************************************************************/ + + /* These next four typemaps handle a function which takes a non-const + * reference to a std::string and modifies the string. */ + %typemap(in,byref=1, phptype="string") string& ($*1_ltype temp) %{ { zval * p = Z_ISREF($input) ? Z_REFVAL($input) : &$input; convert_to_string(p); @@ -73,16 +80,14 @@ namespace std { } %} - %typemap(directorout) string & ($*1_ltype *temp) %{ - if (!EG(exception)) { + %typemap(directorout) string& ($*1_ltype *temp) %{ convert_to_string($input); temp = new $*1_ltype(Z_STRVAL_P($input), Z_STRLEN_P($input)); swig_acquire_ownership(temp); $result = temp; - } %} - %typemap(argout) string & %{ + %typemap(argout) string& %{ if (Z_ISREF($input)) { ZVAL_STRINGL(Z_REFVAL($input), $1->data(), $1->size()); } @@ -90,5 +95,27 @@ namespace std { /* SWIG will apply the non-const typemap above to const string& without * this more specific typemap. */ - %typemap(argout) const string & ""; + %typemap(argout) const string& "" + + /*************************************************************************/ + + /* Alternative ways to handle string& - you can specify how to wrap based + * on the parameter name, e.g. this handles parameters named `str` as + * INOUT: + * + * %apply (std::string& INOUT) (std::string& str); + */ + + %typemap(in) string& INPUT = const string&; + %typemap(in, numinputs=0) string& OUTPUT ($*1_ltype temp) + %{ $1 = &temp; %} + %typemap(argout,fragment="t_output_helper") string& OUTPUT + { + zval o; + ZVAL_STRINGL(&o, $1->data(), $1->size()); + t_output_helper($result, &o); + } + %typemap(in) string& INOUT = const string&; + %typemap(argout) string& INOUT = string& OUTPUT; + } diff --git a/Lib/php/std_string_view.i b/Lib/php/std_string_view.i new file mode 100644 index 000000000..8fff6e100 --- /dev/null +++ b/Lib/php/std_string_view.i @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + * std_string_view.i + * + * SWIG typemaps for std::string_view types + * ----------------------------------------------------------------------------- */ + +%include <exception.i> + +%{ +#include <string_view> +%} + +namespace std { + + %naturalvar string_view; + + class string_view; + + %typemap(typecheck,precedence=SWIG_TYPECHECK_STRINGVIEW) string_view, const string_view& %{ + $1 = (Z_TYPE($input) == IS_STRING) ? 1 : 0; + %} + + %typemap(in, phptype="string") string_view %{ + convert_to_string(&$input); + $1 = std::string_view(Z_STRVAL($input), Z_STRLEN($input)); + %} + + %typemap(in, phptype="string") const string_view& ($*1_ltype temp) %{ + convert_to_string(&$input); + temp = std::string_view(Z_STRVAL($input), Z_STRLEN($input)); + $1 = &temp; + %} + + %typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) string_view %{ + convert_to_string($input); + $result = std::string_view(Z_STRVAL_P($input), Z_STRLEN_P($input)); + %} + + %typemap(out, phptype="string") string_view %{ + ZVAL_STRINGL($result, $1.data(), $1.size()); + %} + + %typemap(directorin) string_view, const string_view& %{ + ZVAL_STRINGL($input, $1.data(), $1.size()); + %} + + %typemap(out, phptype="string") const string_view& %{ + ZVAL_STRINGL($result, $1->data(), $1->size()); + %} + + %typemap(throws) string_view, const string_view& %{ + { + zval swig_exception; + ZVAL_STRINGL(&swig_exception, $1.data(), $1.size()); + zend_throw_exception_object(&swig_exception); + goto fail; + } + %} + + %typemap(throws) string_view*, const string_view* %{ + { + zval swig_exception; + ZVAL_STRINGL(&swig_exception, $1->data(), $1->size()); + zend_throw_exception_object(&swig_exception); + goto fail; + } + %} + +} diff --git a/Lib/php/std_unique_ptr.i b/Lib/php/std_unique_ptr.i new file mode 100644 index 000000000..1bf31595e --- /dev/null +++ b/Lib/php/std_unique_ptr.i @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $descriptor(TYPE *) of $symname"); + return; + } else { + zend_type_error("Expected $descriptor(TYPE *) for argument $argnum of $symname"); + return; + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); +%} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr(&$input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template <class T> class unique_ptr {}; +} diff --git a/Lib/php/std_vector.i b/Lib/php/std_vector.i index e633bc3ad..382b37ca0 100644 --- a/Lib/php/std_vector.i +++ b/Lib/php/std_vector.i @@ -112,5 +112,3 @@ namespace std { %define specialize_std_vector(T) #warning "specialize_std_vector - specialization for type T no longer needed" %enddef - - diff --git a/Lib/php/stl.i b/Lib/php/stl.i index 04f86014f..38aba67b8 100644 --- a/Lib/php/stl.i +++ b/Lib/php/stl.i @@ -7,4 +7,3 @@ %include <std_vector.i> %include <std_map.i> %include <std_pair.i> - diff --git a/Lib/php/swigmove.i b/Lib/php/swigmove.i new file mode 100644 index 000000000..b16a3c544 --- /dev/null +++ b/Lib/php/swigmove.i @@ -0,0 +1,24 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(&$input, &argp, $&1_descriptor, SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $&1_descriptor of $symname"); + return; + } else { + zend_type_error("Expected $&1_descriptor for argument $argnum of $symname"); + return; + } + } + if (!argp) { + zend_type_error("Invalid null reference for argument $argnum of $&1_descriptor of $symname"); + return; + } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/php/typemaps.i b/Lib/php/typemaps.i index c248a588e..718469edc 100644 --- a/Lib/php/typemaps.i +++ b/Lib/php/typemaps.i @@ -25,21 +25,21 @@ * ----------------------------------------------------------------------------- */ %define BOOL_TYPEMAP(TYPE) -%typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) +%typemap(in, phptype="bool") TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ convert_to_boolean(&$input); temp = (Z_TYPE($input) == IS_TRUE); $1 = &temp; %} -%typemap(argout) TYPE *INPUT, TYPE &INPUT ""; -%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; +%typemap(argout) TYPE *INPUT, TYPE &INPUT "" +%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;" %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { zval o; ZVAL_BOOL(&o, temp$argnum); t_output_helper($result, &o); } -%typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) +%typemap(in, phptype="float") TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) %{ convert_to_boolean($input); lvalue = (Z_TYPE_P($input) == IS_TRUE); @@ -52,20 +52,20 @@ %enddef %define DOUBLE_TYPEMAP(TYPE) -%typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) +%typemap(in, phptype="float") TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ temp = (TYPE) zval_get_double(&$input); $1 = &temp; %} -%typemap(argout) TYPE *INPUT, TYPE &INPUT ""; -%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; +%typemap(argout) TYPE *INPUT, TYPE &INPUT "" +%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;" %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { zval o; ZVAL_DOUBLE(&o, temp$argnum); t_output_helper($result, &o); } -%typemap(in) TYPE *REFERENCE (TYPE dvalue), TYPE &REFERENCE (TYPE dvalue) +%typemap(in, phptype="float") TYPE *REFERENCE (TYPE dvalue), TYPE &REFERENCE (TYPE dvalue) %{ dvalue = (TYPE) zval_get_double(&$input); $1 = &dvalue; @@ -77,20 +77,20 @@ %enddef %define INT_TYPEMAP(TYPE) -%typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) +%typemap(in, phptype="int") TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ temp = (TYPE) zval_get_long(&$input); $1 = &temp; %} -%typemap(argout) TYPE *INPUT, TYPE &INPUT ""; -%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; +%typemap(argout) TYPE *INPUT, TYPE &INPUT "" +%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;" %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { zval o; ZVAL_LONG(&o, temp$argnum); t_output_helper($result, &o); } -%typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) +%typemap(in, phptype="int") TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) %{ lvalue = (TYPE) zval_get_long(&$input); $1 = &lvalue; @@ -122,13 +122,11 @@ INT_TYPEMAP(long long); if ((long long)LONG_MIN <= temp$argnum && temp$argnum <= (long long)LONG_MAX) { ZVAL_LONG(&o, (long)temp$argnum); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)temp$argnum); - ZVAL_STRING(&o, temp); + ZVAL_NEW_STR(&o, zend_strpprintf(0, "%lld", (long long)temp$argnum)); } t_output_helper($result, &o); } -%typemap(in) TYPE *REFERENCE (long long lvalue) +%typemap(in, phptype="int|string") TYPE *REFERENCE (long long lvalue) %{ CONVERT_LONG_LONG_IN(lvalue, long long, $input) $1 = &lvalue; @@ -138,9 +136,7 @@ INT_TYPEMAP(long long); if ((long long)LONG_MIN <= lvalue$argnum && lvalue$argnum <= (long long)LONG_MAX) { ZVAL_LONG(&$arg, (long)temp$argnum); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)lvalue$argnum); - ZVAL_STRING(&$arg, temp); + ZVAL_NEW_STR(&$arg, zend_strpprintf(0, "%lld", (long long)lvalue$argnum)); } %} %typemap(argout) long long &OUTPUT @@ -148,11 +144,10 @@ INT_TYPEMAP(long long); if ((long long)LONG_MIN <= *arg$argnum && *arg$argnum <= (long long)LONG_MAX) { ZVAL_LONG($result, (long)(*arg$argnum)); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)(*arg$argnum)); - ZVAL_STRING($result, temp); + ZVAL_NEW_STR($result, zend_strpprintf(0, "%lld", (long long)(*arg$argnum))); } %} + INT_TYPEMAP(unsigned long long); %typemap(argout,fragment="t_output_helper") unsigned long long *OUTPUT { @@ -160,13 +155,11 @@ INT_TYPEMAP(unsigned long long); if (temp$argnum <= (unsigned long long)LONG_MAX) { ZVAL_LONG(&o, temp$argnum); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)temp$argnum); - ZVAL_STRING(&o, temp); + ZVAL_NEW_STR(&o, zend_strpprintf(0, "%llu", (unsigned long long)temp$argnum)); } t_output_helper($result, &o); } -%typemap(in) TYPE *REFERENCE (unsigned long long lvalue) +%typemap(in, phptype="int|string") TYPE *REFERENCE (unsigned long long lvalue) %{ CONVERT_UNSIGNED_LONG_LONG_IN(lvalue, unsigned long long, $input) $1 = &lvalue; @@ -176,9 +169,7 @@ INT_TYPEMAP(unsigned long long); if (lvalue$argnum <= (unsigned long long)LONG_MAX) { ZVAL_LONG($arg, (long)(lvalue$argnum)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)lvalue$argnum); - ZVAL_STRING((*$arg), temp); + ZVAL_NEW_STR((*$arg), zend_strpprintf(0, "%llu", (unsigned long long)lvalue$argnum)); } %} %typemap(argout) unsigned long long &OUTPUT @@ -186,9 +177,7 @@ INT_TYPEMAP(unsigned long long); if (*arg$argnum <= (unsigned long long)LONG_MAX) { ZVAL_LONG($result, (long)(*arg$argnum)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)(*arg$argnum)); - ZVAL_STRING($result, temp); + ZVAL_NEW_STR($result, zend_strpprintf(0, "%llu", (unsigned long long)(*arg$argnum))); } %} @@ -252,7 +241,7 @@ INT_TYPEMAP(unsigned long long); %typemap(argout) unsigned long long &INOUT = unsigned long long *OUTPUT; %typemap(argout) signed char &INOUT = signed char *OUTPUT; -%typemap(in) char INPUT[ANY] ( char temp[$1_dim0] ) +%typemap(in, phptype="string") char INPUT[ANY] ( char temp[$1_dim0] ) %{ convert_to_string(&$input); strncpy(temp, Z_STRVAL($input), $1_dim0); @@ -267,7 +256,7 @@ INT_TYPEMAP(unsigned long long); t_output_helper($result, &o); } -%typemap(in,numinputs=0) void **OUTPUT (int force), +%typemap(in,numinputs=0,phptype="?SWIGTYPE") void **OUTPUT (int force), void *&OUTPUT (int force) %{ /* If they pass NULL by reference, make it into a void* @@ -276,7 +265,8 @@ INT_TYPEMAP(unsigned long long); /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ if (!(Z_ISREF($input) && Z_ISNULL_P(Z_REFVAL($input)))) { /* wasn't a pre/ref/thing, OR anything like an int thing */ - SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); + zend_type_error("Expected reference or NULL for argument $arg of $symname"); + return; } } force=0; diff --git a/Lib/php/utils.i b/Lib/php/utils.i index ed6e08ff4..33db942a9 100644 --- a/Lib/php/utils.i +++ b/Lib/php/utils.i @@ -16,9 +16,9 @@ char * endptr; errno = 0; lvar = (t) strtoll(Z_STRVAL(invar), &endptr, 10); - if (*endptr && !errno) break; - /* FALL THRU */ + if (*endptr == '\0' && !errno) break; } + /* FALL THRU */ default: lvar = (t) zval_get_long(&invar); } @@ -33,9 +33,9 @@ char * endptr; errno = 0; lvar = (t) strtoull(Z_STRVAL(invar), &endptr, 10); - if (*endptr && !errno) break; - /* FALL THRU */ + if (*endptr == '\0' && !errno) break; } + /* FALL THRU */ default: lvar = (t) zval_get_long(&invar); } @@ -63,28 +63,33 @@ } %enddef -%define %pass_by_val( TYPE, CONVERT_IN ) -%typemap(in) TYPE +%define %pass_by_val( TYPE, PHP_TYPE, CONVERT_IN ) +%typemap(in, phptype=PHP_TYPE) TYPE %{ CONVERT_IN($1,$1_ltype,$input); %} -%typemap(in) const TYPE & ($*1_ltype temp) +%typemap(in, phptype=PHP_TYPE) const TYPE & ($*1_ltype temp) %{ CONVERT_IN(temp,$*1_ltype,$input); $1 = &temp; %} %typemap(directorout) TYPE %{ - if (!EG(exception)) { - CONVERT_IN($result, $1_ltype, *$input); - } + CONVERT_IN($result, $1_ltype, *$input); +%} +%typemap(directorout) const TYPE & +%{ + $*1_ltype swig_val; + CONVERT_IN(swig_val, $*1_ltype, *$input); + $1_ltype temp = new $*1_ltype(swig_val); + swig_acquire_ownership(temp); + $result = temp; %} -%typemap(directorout) const TYPE & ($*1_ltype temp) +%typemap(directorfree) const TYPE & %{ - if (!EG(exception)) { - CONVERT_IN(temp, $*1_ltype, *$input); + if (director) { + director->swig_release_ownership(%as_voidptr($input)); } - $result = &temp; %} %enddef |