Discussion:
[Swig-devel] Virtual Function argument is a proxy object instead of the director object
Thomas Maslach
2015-06-04 20:21:35 UTC
Permalink
Hi,

I am using swig 2.0.11. I have the following interface file (built with these options: -threads -python -modern -c++ ) :

%module(directors="1") mod
%feature("director");

%inline %{
class Base {
public:
virtual ~Base(){}
};

class MyClass {
public:
virtual ~MyClass(){}

virtual void directorin(Base* o)=0;
void call_directorin(Base* o){directorin(o);}
};
%}


In Python, when I run the following test, I expect to have that original 'd' object passed into MySubClass.directorin, not a proxy version of 'd'. I know this works in argout cases, so I was hoping it's work on directorin cases as well.

import mod
class Derived(mod.Base): pass
d = Derived()

class MySubClass(mod.MyClass):
def directorin(self, o):
# I want this to return True, as I want the original object.
# But, it returns False
print o == d
c = MySubClass()
c.call_directorin(d)


Is this intended behavior? Or just behavior not implemented yet? I'm assuming it isn't intended behavior (but could be wrong), so I continued investigating. I noticed in the C++ wrap file, my void SwigDirector_MyClass::directorin(Base *o) method was not doing a SWIG_DIRECTOR_CAST. I decided to tweak the wrap generated code by modifying the typemap in swigtype.swg. I changed this code:

%typemap(directorin,noblock=1) SWIGTYPE *, SWIGTYPE *const& {
$input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags);
}

To:

%typemap(directorin,noblock=1) SWIGTYPE *, SWIGTYPE *const& {
Swig::Director *director = SWIG_DIRECTOR_CAST($1);
if (director) {
$input = director->swig_get_self();
Py_INCREF($input);
}
else {
$input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags);
}
}


Upon doing this, I get the result I expected (I see True printed). This typemap is inside a SWIG_DIRECTOR_TYPEMAPS #define, so I think it is safe to do. I haven't modified the SWIGTYPE & case on my side, but I expect that should be changed as well.

Does this make sense to do? Or are there problems with doing this that I haven't foreseen?


Thanks,

Tom
William S Fulton
2015-08-04 05:43:28 UTC
Permalink
Post by Thomas Maslach
Hi,
I am using swig 2.0.11. I have the following interface file (built with
%module(directors="1") mod
%feature("director");
%inline %{
class Base {
virtual ~Base(){}
};
class MyClass {
virtual ~MyClass(){}
virtual void directorin(Base* o)=0;
void call_directorin(Base* o){directorin(o);}
};
%}
In Python, when I run the following test, I expect to have that original
‘d’ object passed into MySubClass.directorin, not a proxy version of ‘d’.
I know this works in argout cases, so I was hoping it’s work on directorin
cases as well.
import mod
class Derived(mod.Base): pass
d = Derived()
# I want this to return True, as I want the original object.
# But, it returns False
print o == d
c = MySubClass()
c.call_directorin(d)
Is this intended behavior? Or just behavior not implemented yet? I’m
assuming it isn’t intended behavior (but could be wrong), so I continued
investigating. I noticed in the C++ wrap file, my void
SwigDirector_MyClass::directorin(Base *o) method was not doing a
SWIG_DIRECTOR_CAST. I decided to tweak the wrap generated code by
%typemap(directorin,noblock=1) SWIGTYPE *, SWIGTYPE *const& {
$input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor,
%newpointer_flags);
}
%typemap(directorin,noblock=1) SWIGTYPE *, SWIGTYPE *const& {
Swig::Director *director = SWIG_DIRECTOR_CAST($1);
if (director) {
$input = director->swig_get_self();
Py_INCREF($input);
}
else {
$input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags);
}
}
Upon doing this, I get the result I expected (I see True printed). This
typemap is inside a SWIG_DIRECTOR_TYPEMAPS #define, so I think it is safe
to do. I haven’t modified the SWIGTYPE & case on my side, but I expect
that should be changed as well.
Does this make sense to do? Or are there problems with doing this that I
haven’t foreseen?
Probably this use case was overlooked during the implementation. Your
proposal seems reasonable to me. I suggest you put together a Github patch
and please include a modification to one of the
Examples/test-suite/python/director*_runme.py testcases with a runtime test.

William

Loading...