Add initial support for PHP8

Testcase director_overload2 is failing, but the rest of the testsuite
passes.
This commit is contained in:
Olly Betts 2021-03-17 12:45:17 +13:00
commit 3584c7d49c
11 changed files with 72 additions and 27 deletions

View file

@ -154,6 +154,10 @@ matrix:
os: linux
env: SWIGLANG=php VER=7.4
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=php VER=8.0
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python # 2.7

View file

@ -51,12 +51,12 @@
<p>
In this chapter, we discuss SWIG's support of PHP. SWIG currently supports
generating wrappers for PHP7. Support for PHP5 was removed in SWIG 4.0.0
and support for PHP4 was removed in SWIG 1.3.37.
generating wrappers for PHP7 and PHP8. Support for PHP5 was removed in SWIG
4.0.0 and support for PHP4 was removed in SWIG 1.3.37.
</p>
<p>
Currently any PHP7 release should work.
Currently any PHP7 or PHP8 release should work.
</p>
<p>

View file

@ -123,7 +123,7 @@ SWIGOCAML Defined when using OCaml
SWIGOCTAVE Defined when using Octave
SWIGPERL Defined when using Perl
SWIGPHP Defined when using PHP (any version)
SWIGPHP7 Defined when using PHP7
SWIGPHP7 Defined when using PHP 7 or later
SWIGPYTHON Defined when using Python
SWIGR Defined when using R
SWIGRUBY Defined when using Ruby

View file

@ -127,7 +127,7 @@ Supported Target Language Options
-lua - Generate Lua wrappers
-octave - Generate Octave wrappers
-perl5 - Generate Perl 5 wrappers
-php7 - Generate PHP 7 wrappers
-php7 - Generate PHP 7 or later wrappers
-python - Generate Python wrappers
-r - Generate R (aka GNU S) wrappers
-ruby - Generate Ruby wrappers

View file

@ -1045,7 +1045,7 @@ ruby_clean:
rm -f *.@OBJEXT@ *$(RUBY_SO)
##################################################################
##### PHP7 ######
##### PHP ######
##################################################################
PHP = @PHP@
@ -1058,7 +1058,7 @@ PHP_SCRIPT = $(SRCDIR)$(RUNME).php
# -------------------------------------------------------------------
php: $(SRCDIR_SRCS)
$(SWIG) -php7 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH)
$(SWIG) -php $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH)
$(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PHP_INCLUDE)
$(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO)
@ -1067,7 +1067,7 @@ php: $(SRCDIR_SRCS)
# --------------------------------------------------------------------
php_cpp: $(SRCDIR_SRCS)
$(SWIG) -php7 -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH)
$(SWIG) -php -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH)
$(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PHP_INCLUDE)
$(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO)

View file

@ -31,7 +31,7 @@ check::is_a($spam,"spam");
check::equal(1,$spam->_foo,"1==spam->_foo");
check::equal(2,$spam->_bar,"2==spam->_bar");
// multiple inheritance not supported in PHP
set_error_handler(NULL, 0); // Don't complain that _baz is unknown.
set_error_handler(function () {return true;}, E_NOTICE|E_WARNING); // Don't complain that _baz is unknown.
check::equal(null,$spam->_baz,"null==spam->_baz");
restore_error_handler();
check::equal(4,$spam->_spam,"4==spam->_spam");

View file

@ -21,7 +21,7 @@ typedef struct SWIGCDATA {
}
%typemap(in) (const void *indata, int inlen) = (char *STRING, int LENGTH);
#elif SWIGPHP7
#elif SWIGPHP
%typemap(out) SWIGCDATA {
ZVAL_STRINGL($result, $1.data, $1.len);

View file

@ -12,7 +12,7 @@
%insert("runtime") "swigerrors.swg"
#ifdef SWIGPHP7
#ifdef SWIGPHP
%{
#include "zend_exceptions.h"
#define SWIG_exception(code, msg) do { zend_throw_exception(NULL, (char*)msg, code); goto thrown; } while (0)

View file

@ -12,8 +12,8 @@ extern "C" {
#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 < 7
# error These bindings need PHP 7 or later - to generate PHP5 bindings use: SWIG < 4.0.0 and swig -php5
#endif
#include "ext/standard/php_string.h"
@ -200,7 +200,11 @@ SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) {
switch (Z_TYPE_P(z)) {
case IS_OBJECT: {
#if PHP_MAJOR_VERSION < 8
HashTable * ht = Z_OBJ_HT_P(z)->get_properties(z);
#else
HashTable * ht = Z_OBJ_HT_P(z)->get_properties(Z_OBJ_P(z));
#endif
if (ht) {
zval * _cPtr = zend_hash_str_find(ht, "_cPtr", sizeof("_cPtr") - 1);
if (_cPtr) {

View file

@ -473,6 +473,20 @@ public:
s_arginfo = NewString("/* arginfo subsection */\n");
arginfo_used = NewHash();
// Add arginfo we'll definitely need for *_alter_newobject and *_get_newobject.
SetFlag(arginfo_used, "1");
Append(s_arginfo,
"ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_1, 0, 0, 0)\n"
" ZEND_ARG_INFO(0,arg1)\n"
"ZEND_END_ARG_INFO()\n");
SetFlag(arginfo_used, "2");
Append(s_arginfo,
"ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_2, 0, 0, 0)\n"
" ZEND_ARG_INFO(0,arg1)\n"
" ZEND_ARG_INFO(0,arg2)\n"
"ZEND_END_ARG_INFO()\n");
/* start the function entry section */
s_entry = NewString("/* entry subsection */\n");
@ -653,8 +667,8 @@ public:
}
Printv(f_begin, s_vdecl, s_wrappers, NIL);
Printv(f_begin, all_cs_entry, "\n\n", s_arginfo, "\n\n", s_entry,
" SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,NULL)\n"
" SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,NULL)\n"
" SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,swig_arginfo_2)\n"
" SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,swig_arginfo_1)\n"
" ZEND_FE_END\n};\n\n", NIL);
Printv(f_begin, s_init, NIL);
Delete(s_header);
@ -689,25 +703,46 @@ public:
// We want to only emit each different arginfo once, as that reduces the
// size of both the generated source code and the compiled extension
// module. To do this, we name the arginfo to encode the number of
// parameters and which (if any) are passed by reference by using a
// sequence of 0s (for non-reference) and 1s (for by references).
// module. The parameters at this level are just named arg1, arg2, etc
// so we generate an arginfo name with the number of parameters and a
// bitmap value saying which (if any) are passed by reference.
ParmList *l = Getattr(n, "parms");
String * arginfo_code = NewStringEmpty();
unsigned long bitmap = 0, bit = 1;
int n_params = 0;
bool overflowed = false;
for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) {
/* Ignored parameters */
if (checkAttribute(p, "tmap:in:numinputs", "0")) {
continue;
}
Append(arginfo_code, GetFlag(p, "tmap:in:byref") ? "1" : "0");
++n_params;
if (GetFlag(p, "tmap:in:byref")) {
bitmap |= bit;
if (bit == 0) overflowed = true;
}
bit <<= 1;
}
String * arginfo_code;
if (overflowed) {
// We overflowed the bitmap so just generate a unique name - this only
// happens for a function with more parameters than bits in a long
// where a high numbered parameter is passed by reference, so should be
// rare in practice.
static int overflowed_counter = 0;
arginfo_code = NewStringf("z%d", ++overflowed_counter);
} else if (bitmap == 0) {
// No parameters passed by reference.
arginfo_code = NewStringf("%d", n_params);
} else {
arginfo_code = NewStringf("%d_%lx", n_params, bitmap);
}
if (!GetFlag(arginfo_used, arginfo_code)) {
// Not had this one before, so emit it.
// Not had this one before so emit it.
SetFlag(arginfo_used, arginfo_code);
Printf(s_arginfo, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_%s, 0, 0, 0)\n", arginfo_code);
for (const char * p = Char(arginfo_code); *p; ++p) {
Printf(s_arginfo, " ZEND_ARG_PASS_INFO(%c)\n", *p);
for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) {
Printf(s_arginfo, " ZEND_ARG_INFO(%d,%s)\n", GetFlag(p, "tmap:in:byref"), Getattr(p, "lname"));
}
Printf(s_arginfo, "ZEND_END_ARG_INFO()\n");
}

View file

@ -2021,7 +2021,7 @@ AC_SUBST(RUBYSO)
AC_SUBST(RUBYDYNAMICLINKING)
#-------------------------------------------------------------------------
# Look for PHP7
# Look for PHP
#-------------------------------------------------------------------------
PHPBIN=
@ -2035,7 +2035,7 @@ if test x"${PHPBIN}" = xno; then
PHP=
else
if test "x$PHPBIN" = xyes; then
AC_CHECK_PROGS(PHP, [php7.4 php7.3 php7.2 php7.1 php7.0 php])
AC_CHECK_PROGS(PHP, [php8.0 php7.4 php7.3 php7.2 php7.1 php7.0 php])
else
PHP=$PHPBIN
fi
@ -2046,12 +2046,14 @@ else
case $PHP in
*7.*)
PHPCONFIG=`echo "$PHP"|sed 's/7\...*$/-config&/'` ;;
*8.*)
PHPCONFIG=`echo "$PHP"|sed 's/8\...*$/-config&/'` ;;
*)
PHPCONFIG=$PHP-config ;;
esac
php_version=`$PHPCONFIG --version 2>/dev/null`
case $php_version in
7.*)
7.*|8.*)
PHPINC=`$PHPCONFIG --includes 2>/dev/null`
if test -n "$PHPINC"; then
AC_MSG_RESULT($PHPINC)
@ -2062,7 +2064,7 @@ else
"")
AC_MSG_RESULT([could not find $PHPCONFIG or obtain PHP version from it]) ;;
*)
AC_MSG_RESULT([found PHP $php_version - not PHP 7]) ;;
AC_MSG_RESULT([found PHP $php_version - not PHP 7 or 8]) ;;
esac
fi
fi