|
View:
New views
7 Messages
—
Rating Filter:
Alert me
|
|
|
SWIG and the Abstract Base Class
The lengthy intro:
I have been employing SWIG in a fairly lightweight context within my application, wrapping an internal function that takes a component reference and then executes it. This provides a highly simplified interface within Python, were I can just call the function with the component name and some arguments. However, my application now has a functional SDK, and it's time for the rubber to meet the road. The philosophy within the system (and the SDK) is "code to an interface". This means that plug-ins for my application must inherit from one or more C++ abstract base classes. In order to directly afford Python programmers the ability to write plug-ins for my application, I need to provide this same functionality to them. SWIG won't completely wrap C++ abstract base classes (rightly so), leaving the wrappers with __init__() functions that throw an AttributeError. So, I need an approach that allows the Python environment to utilize these interfaces such that they are duck-typed as a valid plug-in for my application. The (imagined) approach: The SWIG documentation talks about wrapping C++ abstract classes to the extent that it (basically) can't be usefully done. It does not, from what I've been able to find, talk about how it can be done. So, the approach I'm going to try (and for which I would appreciate some sage feedback) is to first create "shell" proxy classes in C++ that inherit from my SDK's interfaces. In a file called, for example, "AbstractWrappers.h", where the inherited classes are those with pure virtual methods, they would look something like this: [...] class ProxyPlugin : public SDK::Plugin { public: ProxyPlugin() : Plugin() {} virtual ~ProxyPlugin() {} virtual void* get_interface(unsigned int interface_id) { return 0; } }; [...] class ProxyCommand : public SDK::Command { public: ProxyCommand() : Command() {} virtual ~ProxyCommand() {} virtual void execute(Context& ctx) {} virtual void execute_without_item() {} virtual void execute(const ItemRef& item) {} }; [...] // Convenience proxy class ProxyCommandPlugin : public ProxyPlugin, public ProxyCommand { [...] } And so forth. The proxy classes would implement do-nothing versions of the pure virtual methods, leaving the Python versions to override. Then, in the SWIG interface file, I would wrap these proxy classes: [...] %include <SDK/Plugin.h> %include <SDK/interfaces/CommandInterface.h> %include "AbstractWrappers.h" [...] With the proxy classes wrapped, I would then turn on the "directors" feature for each of them: %module (naturalvar="1",directors="1") PySDK [...] %include <SDK/Plugin.h> %include <SDK/interfaces/CommandInterface.h> %feature("director") ProxyPlugin; %feature("director") ProxyCommand; %feature("director") ProxyCommandPlugin; %include "AbstractWrappers.h" Then, in the Python environment, I would inherit from the proxy classes in order to create my Pythonic application plug-in classes: class CommandPlugin(object, ProxyCommandPlugin) def __init__(self): super(CommandPlugin, self).__init__() [...] Which would then allow me to interact with the Python CommandPlugin class instance in C++ as though it were either a SDK::Plugin or an SDK::Command. The question: Is this the best way to approach wrapping C++ abstract base classes, or am I way off base? Does SWIG offer something more elegant than this? I'd like an approach that makes plug-in writing within the scripting environment as close as possible to that of the C++ (binary) case, so if there are improvements to be made on this approach, I would greatly appreciate knowing about it before I move forward. All my thanks. Render me gone, |||
Bob ^(===)^
---------------------------------oOO--(_)--OOo---------------------------------
The world needs more cults. They attract stupidity like a
magnet attracts metal, and they're self cleaning.
------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Swig-user mailing list Swig-user@... https://lists.sourceforge.net/lists/listinfo/swig-user |
|
|
Re: SWIG and the Abstract Base ClassAm 25.09.2009, 04:56 Uhr, schrieb Bob Hood <bhood2@...>:
> > The question: > > Is this the best way to approach wrapping C++ abstract base classes, or > am I way off base? Does SWIG offer something more elegant than this? > I'd like an approach that makes plug-in writing within the scripting > environment as close as possible to that of the C++ (binary) case, so if > there are improvements to be made on this approach, I would greatly > appreciate knowing about it before I move forward. Sorry for the half-finished last mail. When I hit enter to go into the next line my mail client went all crazy, opened windows and sent the message. From your explanation I couldn't understand why you are creating those shell proxy classes. Iirc there are a few places in my own code where I just inherit from a swig wrapped abstract base class. I've enabled directors on this abstract base class before of course. Then I can just use it like I'd do in C++. E.g. On the C++ side class InheritMe { public: virtual int DoSomething() = 0; }; Then on the python side: import myModule class Derived(myModule.InheritMe): def DoSomething(self): return 666 should just work. -Matthias ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Swig-user mailing list Swig-user@... https://lists.sourceforge.net/lists/listinfo/swig-user |
|
|
Re: SWIG and the Abstract Base ClassFrom your explanation I couldn't understand why you are creating those shell proxy classes. For some reason, for me, it didn't. Any attempts to use the ABCs in this fashion threw the __init__()'s AttributeError. I'll have a look again and see if I'm doing something wrong. Thanks for the feedback, Matthias. Render me gone, |||
Bob ^(===)^
---------------------------------oOO--(_)--OOo---------------------------------
The world needs more cults. They attract stupidity like a
magnet attracts metal, and they're self cleaning.
------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Swig-user mailing list Swig-user@... https://lists.sourceforge.net/lists/listinfo/swig-user |
|
|
Re: SWIG and the Abstract Base ClassNitro wrote:
> From your explanation I couldn't understand why you are creating those > shell proxy classes. Ok, the problem I'm running into is the need to initialize the base class. In the original post, you can see that I'm needing to propagate the initialization to the abstract base class: [...] class ProxyPlugin : public SDK::Plugin { public: ProxyPlugin() : Plugin() [...] This means that I cannot simply perform this action from a direct inheritance within Python without triggering SWIG's AttributeError throw in the wrapper. In other words, this direct inheritance: class CommandPlugin(object, Plugin) def __init__(self): super(CommandPlugin, self).__init__() would cause the AttributeError to be thrown. In your example, your arrangement doesn't appear to have a need to call any methods in the abstract base class, so you probably would not be encountering this. This is why I went with the proxy classes. Direct inheritance of an abstract base class that requires initialization gives me exception heartburn using SWIG. This is the main issue I'm trying to address. Render me gone, ||| Bob ^(===)^ ---------------------------------oOO--(_)--OOo--------------------------------- The world needs more cults. They attract stupidity like a magnet attracts metal, and they're self cleaning. ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Swig-user mailing list Swig-user@... https://lists.sourceforge.net/lists/listinfo/swig-user |
|
|
Re: SWIG and the Abstract Base ClassAm 27.09.2009, 19:29 Uhr, schrieb Bob Hood <bhood2@...>:
> class CommandPlugin(object, Plugin) > def __init__(self): > super(CommandPlugin, self).__init__() > > would cause the AttributeError to be thrown. Attached is a very simplistic interface file. Command line to run: "swig -python -c++ test.i". I used swig 1.3.39. I didn't compile the resulting wrapper code, just looked at the generated python code. It doesn't contain the AttributeError you mention. The AttributeError in __init__ is often generated if you do not apply directors to the base class properly. The second problem is your python code does not work for me. It should look like class CommandPlugin(Plugin): def __init__(self): super(CommandPlugin, self).__init__() Note the difference in the base classes. Plugin already inherits from object, so no need to inherit from it again. Of course if you absolutely want to inherit from object again, you can do class CommandPlugin(Plugin, object): def __init__(self): super(CommandPlugin, self).__init__() Note the difference in the order of the base classes. HTH, -Matthias Appendix A: generated python __init__ code: def __init__(self, *args): if self.__class__ == BaseClass: _self = None else: _self = self this = _test.new_BaseClass(_self, *args) try: self.this.append(this) except: self.this = this ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Swig-user mailing list Swig-user@... https://lists.sourceforge.net/lists/listinfo/swig-user |
|
|
Re: SWIG and the Abstract Base ClassApologies for the delays in replying. I am ill. :(
Nitro wrote: > I didn't compile the resulting wrapper code, just looked at the > generated python code. It doesn't contain the AttributeError you > mention. The AttributeError in __init__ is often generated if you do > not apply directors to the base class properly. Which is precisely what I was doing wrong, it would seem. I don't know how I missed that. I must have done something incorrectly from the outset, and it snowballed from there. Vielen Dank, Matthias, for your patience and your help. A second set of eyes on a problem is always a tremendous benefit. Render me gone, ||| Bob ^(===)^ ---------------------------------oOO--(_)--OOo--------------------------------- The world needs more cults. They attract stupidity like a magnet attracts metal, and they're self cleaning. ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Swig-user mailing list Swig-user@... https://lists.sourceforge.net/lists/listinfo/swig-user |
|
|
Re: SWIG and the Abstract Base ClassAm 29.09.2009, 17:33 Uhr, schrieb Bob Hood <bhood2@...>:
> Apologies for the delays in replying. I am ill. :( > > Nitro wrote: >> I didn't compile the resulting wrapper code, just looked at the >> generated python code. It doesn't contain the AttributeError you >> mention. The AttributeError in __init__ is often generated if you do >> not apply directors to the base class properly. > > Which is precisely what I was doing wrong, it would seem. I don't know > how I missed that. I must have done something incorrectly from the > outset, and it snowballed from there. Vielen Dank, Matthias, for your > patience and your help. A second set of eyes on a problem is always a > tremendous benefit. I'm glad I could help. A useful thing especially for debugging swig related problems is to write a very simple interface file containing the problem. Very often this will lead to an immediate insight into what's going wrong and why. -Matthias ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ Swig-user mailing list Swig-user@... https://lists.sourceforge.net/lists/listinfo/swig-user |
| Free embeddable forum powered by Nabble | Forum Help |