Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Extending classes written in C++ using SWIG

Reply
Thread Tools

Extending classes written in C++ using SWIG

 
 
Lars Moastuen
Guest
Posts: n/a
 
      11-25-2004
Im trying to extend a class written in C++ in Python and use this
extended class in a C++ call... I made an example to clarify:

-- Foo.h --
#ifndef FOO_H
#define FOO_H

#include <iostream>
using namespace std;

class Foo;
class Bar;

class Bar
{
public:
Bar() {};
~Bar() {};
virtual char* DoBar() const { return "Bar"; };
};

class Foo
{
public:
Foo() {};
~Foo() {};
virtual void DoFoo(Bar* someBar) { cout << someBar->DoBar() << endl;
};
};

#endif

-- Foo.cpp --
#include "Foo.h"

-- swig.i --
%module test
%{
#include "Foo.h"
%}

%include "Foo.h"

-- UseFoo.py --
#!/usr/bin/env python

from test import *;

class ExtendedBar(Bar):
def __init__(self):
Bar.__init__(self);

def DoBar(self):
return "ExtendedBar";

bar = ExtendedBar();
foo = Foo();
foo.DoFoo(bar);

------------

I now expect to get "ExtendedBar" as output from UseFoo.py (since I've
declared DoBar() as virtual, but I get "Bar".... I'm using SWIG 1.3.1
to create the bindings from Python to C++. (swig -python -c++)

Can anyone tell me why? Is there a way to remedy this??

Thx,
Lars Moastuen
 
Reply With Quote
 
 
 
 
Jacek Generowicz
Guest
Posts: n/a
 
      11-25-2004
(Lars Moastuen) writes:

> class Bar
> {
> public:
> Bar() {};
> ~Bar() {};
> virtual char* DoBar() const { return "Bar"; };
> };
>
> class Foo
> {
> public:
> Foo() {};
> ~Foo() {};
> virtual void DoFoo(Bar* someBar) { cout << someBar->DoBar() << endl;
> };
> };


> class ExtendedBar(Bar):
> def __init__(self):
> Bar.__init__(self);
>
> def DoBar(self):
> return "ExtendedBar";
>
> bar = ExtendedBar();
> foo = Foo();
> foo.DoFoo(bar);


> I now expect to get "ExtendedBar" as output from UseFoo.py (since I've
> declared DoBar() as virtual, but I get "Bar"


> Can anyone tell me why?


Because "someBar->DoBar()" uses the vtable of the C++ dynamic type to
decide which actual DoBar method to call. Unfortunately there is no
C++ type corresponding to your ExtendedBar, there is no vtable for
your ExtendedBar type in C++. C++ only knows about C++ types; it is
unaware of the existence of Python types. Inside your Python instance
of ExtendedBar you are holding on to an instance of a C++ Bar.

> Is there a way to remedy this??


I don't know whether SWIG provides a boxed solution for this sort of
problem. One approach is to override the DoBar method in a subclass of
Bar in C++, and make that method pass the 'dispatch request' up into
Python. Then you expose the wrapper class in Python, rather than Bar
itself.

It looks something like this:

struct PseudoBar : public Bar {
PyObject* self; // the Python instance wrapping this C++ instance
void DoFoo () {
PyObject_CallMethod(this->self, "DoFoo", "");
}
};

Of course, you'll need to augment this with checks to ensure that
there really is something overriding the method, otherwise you'll end
up in an infinite loop ... but hopefully you get the idea. It's all a
bit tedious.
 
Reply With Quote
 
 
 
 
Phil Thompson
Guest
Posts: n/a
 
      11-25-2004
> (Lars Moastuen) writes:
>
>> class Bar
>> {
>> public:
>> Bar() {};
>> ~Bar() {};
>> virtual char* DoBar() const { return "Bar"; };
>> };
>>
>> class Foo
>> {
>> public:
>> Foo() {};
>> ~Foo() {};
>> virtual void DoFoo(Bar* someBar) { cout << someBar->DoBar() << endl;
>> };
>> };

>
>> class ExtendedBar(Bar):
>> def __init__(self):
>> Bar.__init__(self);
>>
>> def DoBar(self):
>> return "ExtendedBar";
>>
>> bar = ExtendedBar();
>> foo = Foo();
>> foo.DoFoo(bar);

>
>> I now expect to get "ExtendedBar" as output from UseFoo.py (since I've
>> declared DoBar() as virtual, but I get "Bar"

>
>> Can anyone tell me why?

>
> Because "someBar->DoBar()" uses the vtable of the C++ dynamic type to
> decide which actual DoBar method to call. Unfortunately there is no
> C++ type corresponding to your ExtendedBar, there is no vtable for
> your ExtendedBar type in C++. C++ only knows about C++ types; it is
> unaware of the existence of Python types. Inside your Python instance
> of ExtendedBar you are holding on to an instance of a C++ Bar.
>
>> Is there a way to remedy this??

>
> I don't know whether SWIG provides a boxed solution for this sort of
> problem. One approach is to override the DoBar method in a subclass of
> Bar in C++, and make that method pass the 'dispatch request' up into
> Python. Then you expose the wrapper class in Python, rather than Bar
> itself.
>
> It looks something like this:
>
> struct PseudoBar : public Bar {
> PyObject* self; // the Python instance wrapping this C++ instance
> void DoFoo () {
> PyObject_CallMethod(this->self, "DoFoo", "");
> }
> };
>
> Of course, you'll need to augment this with checks to ensure that
> there really is something overriding the method, otherwise you'll end
> up in an infinite loop ... but hopefully you get the idea. It's all a
> bit tedious.


If SWIG really requires you to do this by hand (I'm surprised) then you
might want to look at SIP (http://www.riverbankcomputing.co.uk/sip/). SIP
generates code that does exactly what you suggest so that bindings behave
as the OP was expecting.

Phil

 
Reply With Quote
 
Lars Moastuen
Guest
Posts: n/a
 
      11-26-2004
Thx for your replies.

It seems I have created an example I thought were equal to my problem,
but it turned out that wasn't the case. I'm trying to figure out what
the difference is, but I find the classes quite similar to the example
below (too big to post here)... However, this problem can be solved by
using "directors" (http://www.swig.org/Doc1.3/Python.html#directors),
mine cannot...

Im currently testing if Boost.Python does the job better, but seems I
run into the same problem... I suspect it has something to do with STL
list or something, but I'm not sure yet...

Will post if I manage to create an example or if I find a solution.


"Phil Thompson" <> wrote in message news:<mailman.6788.1101400792.5135.python->...
> > (Lars Moastuen) writes:
> >
> >> class Bar
> >> {
> >> public:
> >> Bar() {};
> >> ~Bar() {};
> >> virtual char* DoBar() const { return "Bar"; };
> >> };
> >>
> >> class Foo
> >> {
> >> public:
> >> Foo() {};
> >> ~Foo() {};
> >> virtual void DoFoo(Bar* someBar) { cout << someBar->DoBar() << endl;
> >> };
> >> };

>
> >> class ExtendedBar(Bar):
> >> def __init__(self):
> >> Bar.__init__(self);
> >>
> >> def DoBar(self):
> >> return "ExtendedBar";
> >>
> >> bar = ExtendedBar();
> >> foo = Foo();
> >> foo.DoFoo(bar);

>
> >> I now expect to get "ExtendedBar" as output from UseFoo.py (since I've
> >> declared DoBar() as virtual, but I get "Bar"

>
> >> Can anyone tell me why?

> >
> > Because "someBar->DoBar()" uses the vtable of the C++ dynamic type to
> > decide which actual DoBar method to call. Unfortunately there is no
> > C++ type corresponding to your ExtendedBar, there is no vtable for
> > your ExtendedBar type in C++. C++ only knows about C++ types; it is
> > unaware of the existence of Python types. Inside your Python instance
> > of ExtendedBar you are holding on to an instance of a C++ Bar.
> >
> >> Is there a way to remedy this??

> >
> > I don't know whether SWIG provides a boxed solution for this sort of
> > problem. One approach is to override the DoBar method in a subclass of
> > Bar in C++, and make that method pass the 'dispatch request' up into
> > Python. Then you expose the wrapper class in Python, rather than Bar
> > itself.
> >
> > It looks something like this:
> >
> > struct PseudoBar : public Bar {
> > PyObject* self; // the Python instance wrapping this C++ instance
> > void DoFoo () {
> > PyObject_CallMethod(this->self, "DoFoo", "");
> > }
> > };
> >
> > Of course, you'll need to augment this with checks to ensure that
> > there really is something overriding the method, otherwise you'll end
> > up in an infinite loop ... but hopefully you get the idea. It's all a
> > bit tedious.

>
> If SWIG really requires you to do this by hand (I'm surprised) then you
> might want to look at SIP (http://www.riverbankcomputing.co.uk/sip/). SIP
> generates code that does exactly what you suggest so that bindings behave
> as the OP was expecting.
>
> Phil

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Generally, are the programs written by C++ slower than written by C10% ? KaiWen C++ 102 09-14-2011 11:12 PM
extending ta-lib using SWIG BENI Ruby 0 03-13-2007 08:20 AM
extending python with a C-written dll Jean-Baptiste PERIN Python 24 12-21-2004 08:03 PM
after embedding and extending python (using swig) problem importing (non-core) modules stefan Python 3 12-08-2004 07:11 PM
Re: Can a usercontrol written in C# be used in Web Forms that is written in VB.Net? Steve C. Orr, MCSD ASP .Net 1 08-24-2003 12:06 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57