[Kde-bindings] [PATCH] Correct handling of virtual methods in Smoke

Arno Rehn arno at arnorehn.de
Wed Dec 31 16:13:13 UTC 2008


Hi,

the current version of Smoke has a bug that is quite a showstopper if we want 
to create KParts with a bindings language.
If we call a virtual method via Smoke, it will always choose the base 
implementation. That's no problem if the target class is wrapped in smoke, 
since we then cast to that class and thus the correct method is called. But if 
it isn't wrapped, it will simply call the implementation of the last super 
class that's wrapped in smoke.
That's the case with KPluginFactory::create(). In the Ruby and C# bindings we 
subclassed KPluginFactory and provided our own implementation of create(). If 
we create a KPart in Ruby or C# and use it from C++, it will detect that it's 
actually a krubypluginfactory/kimonopluginfactory and call the correct 
create().
If we embed it in a Ruby or C# app, the bindings will request that create() is 
called on the KPluginFactory instance. This will result in a call to
    void x_15(Smoke::Stack x) {
	// create(const char*, QWidget*, QObject*, const QList<QVariant>&, const 
QString&)
	QObject* xret = this->KPluginFactory::create((const char*)x[1].s_voidp,
(QWidget*)x[2].s_class,(QObject*)x[3].s_class,*(const QList<QVariant> 
*)x[4].s_voidp,*(const QString *)x[5].s_voidp);
	x[0].s_class = (void*)xret;
    }

'this->KPluginFactory::create(...)' will only call the base implementation of 
create(), and not our custom one of krubypluginfactory/kimonopluginfactory and 
thus lead to the wrong behaviour.

I've created a patch for kalyptus that fixes this issue. It splits the x_* 
classes into x_Foo and xc_Foo.
x_Foo only contains the overrides for virtual methods and is the class that 
should be instantiated, xc_Foo contains the x_1(), x_2(), ... calls, so we can 
simply call 'create()' without the classname and thus let the correct method 
be inferred at runtime.
Since there are cases when we explicitly want to call the base implementation 
from a bindings language, I make use of the C++ RTTI information with 
typeid(...) to detect whether the current instance was created in real C++ 
code or explicitly created by the user (i.e. the type is of the form x_Foo). 
In the latter case we always call the base implementation, since that's what 
the user probably wants to do.

The patch increases the time that's needed to generate the sources to quite 
some extent because we need to check if a method is an override of a virtual 
method.

Now, the reason why I'm explaining all that and sending you this patch is that 
I'm not sure if this works for everyone or if there's a better and especially 
faster way to implement it. I also don't know if this should be merged for 4.2 
or if we should wait till 4.2.1.
Could you please test it and report whether it works or not? =)

-- 
Arno Rehn
arno at arnorehn.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: kalyptusCxxToSmoke.patch
Type: text/x-patch
Size: 13574 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/kde-bindings/attachments/20081231/2f05df30/attachment.patch>


More information about the Kde-bindings mailing list