diff options
author | Olly Betts <olly@survex.com> | 2022-10-18 10:28:17 +1300 |
---|---|---|
committer | Olly Betts <olly@survex.com> | 2022-10-18 10:28:17 +1300 |
commit | 747a6a264f56711c7b725cf883ef623e01b65922 (patch) | |
tree | 91ab34ec9f7e5cc9e07015ae6fc3158833357b38 | |
parent | d8a028601247e96c15bbaac08100cce0401f186e (diff) | |
download | swig-747a6a264f56711c7b725cf883ef623e01b65922.tar.gz |
[php] Fix handling of multi-module cases
Look up unknown base classes using SWIG_MangledTypeQueryModule().
Revert to using SWIG_TypeCheck() instead of SWIG_TypeCheckStruct()
as the latter doesn't seem to work for this case (at least for PHP
right now).
Add mod_runme.php as a regression test for this.
Adjust the PHP test harness not to set up reflection for the module
unless it's actually needed for a testcase. Currently the approach
to find the module name doesn't work for multi-module testcases.
See #2126
-rw-r--r-- | Examples/Makefile.in | 3 | ||||
-rw-r--r-- | Examples/test-suite/php/Makefile.in | 23 | ||||
-rw-r--r-- | Examples/test-suite/php/mod_runme.php | 9 | ||||
-rw-r--r-- | Examples/test-suite/php/tests.php | 33 | ||||
-rw-r--r-- | Lib/php/phprun.swg | 2 | ||||
-rw-r--r-- | Source/Modules/php.cxx | 9 |
6 files changed, 56 insertions, 23 deletions
diff --git a/Examples/Makefile.in b/Examples/Makefile.in index e28e48149..46193348d 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1215,6 +1215,9 @@ php_cpp: $(SRCDIR_SRCS) php_run: $(RUNTOOL) $(PHP) -n -d extension_dir=. -d extension=$(PHP_EXTENSION) -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});if(strlen($$argv[1]))include($$argv[1]);' '$(PHP_SCRIPT)' $(RUNPIPE) +php_run_multi: + $(RUNTOOL) $(PHP) -n -d extension_dir=. `while read e ; do echo ' -d extension=$(TARGETPREFIX)'"$$e"'@PHP_SO@' ; done < $(PHP_EXTENSION_LIST)` -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});if(strlen($$argv[1]))include($$argv[1]);' '$(PHP_SCRIPT)' $(RUNPIPE) + # ----------------------------------------------------------------- # Version display # ----------------------------------------------------------------- diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index c918581bf..3811bd024 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -57,10 +57,18 @@ missingtests: missingcpptests missingctests +$(swig_and_compile_c) +$(run_testcase) +# Trying to load the modules for imports.multicpptest fails with: +# +# Warning: Function registration failed - duplicate name - global_test in Unknown on line 0 +# Segmentation fault +# +# This was previously hidden because we didn't even try to load the modules for +# .multicpptest testcases, so for now just do the parts of the test we did +# before. FIXME: Fix this! %.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) - +$(run_testcase) + +[ "$*" = "imports" ] || $(run_multi_testcase) # Smart target %.test: @@ -72,14 +80,23 @@ missingtests: missingcpptests missingctests $(MAKE) $*.multicpptest # Runs the testcase. Tries to run testcase_runme.php, and if that's not found, -# at least test that the module loads without errors, except for multicpptests. +# at least test that the module loads without errors. run_testcase = \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*@PHP_SO@ PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php_run; \ - elif [ ! -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ + else \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*@PHP_SO@ PHP_SCRIPT= RUNTOOL='$(RUNTOOL)' php_run; \ fi +# Runs a multicpptest testcase. Tries to run testcase_runme.php, and if that's +# not found, at least test that the modules load without errors. +run_multi_testcase = \ + if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION_LIST=$(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php_run_multi; \ + else \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION_LIST=$(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list PHP_SCRIPT= RUNTOOL='$(RUNTOOL)' php_run_multi; \ + fi + # Clean: remove the generated PHP-specific files %.clean: @rm -f php_$*.h diff --git a/Examples/test-suite/php/mod_runme.php b/Examples/test-suite/php/mod_runme.php new file mode 100644 index 000000000..6e485ce80 --- /dev/null +++ b/Examples/test-suite/php/mod_runme.php @@ -0,0 +1,9 @@ +<?php + +require "tests.php"; + +$c = new C(); +$d = new D(); +$d->DoSomething($c); + +check::done(); diff --git a/Examples/test-suite/php/tests.php b/Examples/test-suite/php/tests.php index 0ff20e377..7213d7094 100644 --- a/Examples/test-suite/php/tests.php +++ b/Examples/test-suite/php/tests.php @@ -9,18 +9,19 @@ class check { private static $_werror = false; - // This is called automatically at the end of this file. - static function init() { - foreach(get_included_files() as $f) { - $module_name = preg_filter('/.*\/([^\/]+)_runme\.php$/', '\1', $f); - if ($module_name !== null) break; - } - if ($module_name === null) { - print("Failed to determine module name from get_included_files()\n"); - exit(1); + static function get_extension() { + if (self::$_extension === null) { + foreach(get_included_files() as $f) { + $module_name = preg_filter('/.*\/([^\/]+)_runme\.php$/', '\1', $f); + if ($module_name !== null) break; + } + if ($module_name === null) { + print("Failed to determine module name from get_included_files()\n"); + exit(1); + } + self::$_extension = new ReflectionExtension($module_name); } - - self::$_extension = new ReflectionExtension($module_name); + return self::$_extension; } static function werror($v) { @@ -92,7 +93,7 @@ class check { if (! is_array($classes)) $classes=array($classes); $message=array(); $missing=array(); - $extra = array_flip(array_filter(self::$_extension->getClassNames(), + $extra = array_flip(array_filter(self::get_extension()->getClassNames(), function ($e) { return !preg_match('/^SWIG\\\\/', $e); })); foreach($classes as $class) { if (! class_exists($class)) $missing[]=$class; @@ -109,7 +110,7 @@ class check { if (! is_array($functions)) $functions=array($functions); $message=array(); $missing=array(); - $extra = self::$_extension->getFunctions(); + $extra = self::get_extension()->getFunctions(); foreach ($functions as $func) { if (! function_exists($func)) $missing[]=$func; else unset($extra[$func]); @@ -127,7 +128,7 @@ class check { if (! is_array($globals)) $globals=array($globals); $message=array(); $missing=array(); - $extra = self::$_extension->getFunctions(); + $extra = self::get_extension()->getFunctions(); foreach ($globals as $glob) { if (! function_exists($glob . "_get") && ! function_exists($glob . "_set")) $missing[]=$glob; else { @@ -149,7 +150,7 @@ class check { if (! is_array($constants)) $constants=array($constants); $message=array(); $missing=array(); - $extra = self::$_extension->getConstants(); + $extra = self::get_extension()->getConstants(); unset($extra['swig_runtime_data_type_pointer']); foreach($constants as $constant) { if (! defined($constant)) $missing[]=$constant; @@ -213,5 +214,3 @@ class check { # print $_SERVER[argv][0]." ok\n"; } } - -check::init(); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 538b7e165..d3ad0d26a 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -193,7 +193,7 @@ SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_o /* They don't care about the target type, so just pass on the pointer! */ *ptr = value->ptr; } else { - swig_cast_info *tc = SWIG_TypeCheckStruct(value->type, ty); + swig_cast_info *tc = SWIG_TypeCheck(value->type->name, ty); if (tc) { int newmemory = 0; *ptr = SWIG_TypeCast(tc, value->ptr, &newmemory); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index a2e741215..fd53d41f7 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1836,13 +1836,18 @@ public: base_class = NewString("Exception"); } - if (Equal(base_class, "Exception")) { + if (!base_class) { + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); + } else if (Equal(base_class, "Exception")) { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); } else if (is_class_wrapped(base_class)) { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class); Setattr(php_parent_class, class_name, base_class); } else { - Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); + Printf(s_oinit, " {\n"); + Printf(s_oinit, " swig_type_info *type_info = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, \"_p_%s\");\n", base_class); + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, (zend_class_entry*)(type_info ? type_info->clientdata : NULL));\n", class_name); + Printf(s_oinit, " }\n"); } if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) { |