I've been working with SWIG for Python, Perl and PHP5 and have found the following to be a problem on PHP5 only. Using SWIG 1.3.36.
Wrap the following C++ for php5:
== example.h ==
struct bar1 { int x };
struct bar2 { char y };
void func (bar1 t)
{
printf("in func for bar1");
}
void func (bar2 t)
{
printf("in func for bar2");
}
== example.i ==
%module example
%{
#include "example.h"
%}
%include "example.h"
The top-level C++ wrapper produced for func looks like this:
ZEND_NAMED_FUNCTION(_wrap_func) {
int argc;
zval **argv[1];
argc = ZEND_NUM_ARGS();
zend_get_parameters_array_ex(argc,argv);
if (argc == 1) {
int _v;
/* typecheck SWIGTYPE */
if (_v) {
return _wrap_func__SWIG_0(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
}
if (argc == 1) {
int _v;
/* typecheck SWIGTYPE */
if (_v) {
return _wrap_func__SWIG_1(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
}
SWIG_ErrorCode() = E_ERROR;
SWIG_ErrorMsg() = "No matching function for overloaded 'func'";
zend_error(SWIG_ErrorCode(),SWIG_ErrorMsg());
}
Instead of checking the type for bar1 or bar2, there's just the "typecheck SWIGTYPE" comment. Consequently, only _wrap_func__SWIG_0 will ever be called and if the parameter to func is bar2, a type error is produced at run time.
Rather than the "typecheck SWIGTYPE" comment, I would expect:
{
void *tmp;
_v = (SWIG_ConvertPtr( *argv[0], (void**)&tmp, SWIGTYPE_p_bar1, 0) >= 0);
}
and the equivalent for bar2.
This only seems to happen for non-primitive types as arguments for the overloaded functions.
Thanks
Thanks for including complete examples in your reports, but it would be more helpful if you could attach the files rather than pasting them into the description.
Anyway, this is because of this typemap in Lib/php/php.swg (the filenames there might be based on php4 in the version you're using):
%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE
" /* typecheck SWIGTYPE */ "
If you replace that with your suggested code, does this fix the problem for you?
Ah, that explains where the comment is coming from!
I can't replace that bit with the suggested code verbatim, as the code needs to be slightly different for the two functions bar1 and bar2. The generic code would be something like:
{
void *tmp;
_v = (SWIG_ConvertPtr( *$input, (void **)&tmp, $1_descriptor, 0) >= 0);
}
Although $input is correctly replaced with argv[0], $1_descriptor is replaced with SWIGTYPE_bar1 and SWIGTYPE_bar2, rather than SWIGTYPE_p_bar1 and SWIGTYPE_p_bar2, so the type comparison still fails. I haven't come across a suitable variable to replace this type.
$&1_descriptor should do what you want (see Typemaps.html in the manual for details).
Yes, that does the trick! Thanks very much.
Patch committed to fix this bug
I've committed a patch which I believe fixes this issue to SVN trunk. I've attached the patch and would appreciate it if you could verify that it fixes things for you.
File Added: bug2095186.patch