473,465 Members | 1,962 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Extending classes written in C++ using SWIG

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
Jul 18 '05 #1
3 3488
tj*****@start.no (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.
Jul 18 '05 #2
> tj*****@start.no (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

Jul 18 '05 #3
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" <ph**@riverbankcomputing.co.uk> wrote in message news:<ma**************************************@pyt hon.org>...
tj*****@start.no (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

Jul 18 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Harish | last post by:
I am using Python2.3 version with SWIG-1.3.19 to access C++ interface provided by a DLL. Some of its function returns MFC class objects like CString , CMap. I tried to generate wrapper for these...
7
by: Bo Peng | last post by:
Dear Python group: I am planning on an application that involves several complicated C++ classes. Basically, there will be one or two big data objects and some "action" objects that can act on...
24
by: Jean-Baptiste PERIN | last post by:
Hi, I'm trying to make a windows dll reachable from a python script .. and I'm encountering troubles during link step .. I use "lcc" to compile and link I use python 2.3 under win XP ...
1
by: Eduardo Rodrigues | last post by:
How can I load a module (written in C as a shared library (.so)) through "PyRun_SimpleString"? I've tried "from <module> import *", but a got a message: ImportError: No module named <module> ...
3
by: Marco Meoni | last post by:
Hi all! I've a problem with a C++ class that has to be included in a python application. One way to do it is Extending and Embedding the Python Interpreter Now i have 2 questions 1) Is there a...
1
by: jeremito | last post by:
I am trying to learn how to extend and/or embed Python. I have looked at the document "Extending and Embedding the Python Interpreter" and also "Python/C API Reference Manual. In the examples...
6
by: Qun Cao | last post by:
Hi Everyone, I am a beginner on cross language development. My problem at hand is to build a python interface for a C++ application built on top of a 3D game engine. The purpose of this python...
0
by: Carl Douglas | last post by:
Hi Python fans, I am developing a DLL that is loaded by a host application on windows. I'm using python 2.5. My DLL uses an embedded python interpreter which can access the host application...
0
by: vishnu | last post by:
Hello All, I have embedded python 2.5 in to my C application. As we need the python scripts to run in multi threaded environment I have used Py_NewInterpreter() and Py_EndInterpreter each time I...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.