Added a simple example where the current universal

Java wrapping mechanism doesn't work, showing the
need to use a different way to wrap polymorphic classes.

They are two runtime examples: one for java, which is
failing, and one for python, which works fine.

Detailed description of the case can be found
in the three files committed.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@5582 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2003-12-22 06:26:44 +00:00
commit c5cf57b254
3 changed files with 172 additions and 0 deletions

View file

@ -0,0 +1,44 @@
// virtual_poly test
import virtual_poly.*;
public class virtual_poly_runme {
static {
try {
System.loadLibrary("virtual_poly");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
NDouble d = new NDouble(3.5);
NInt i = new NInt(2);
//
// These two natural 'copy' forms fail, only java and csharp
// because no polymorphic return types are supported.
// But we can live with this restriction, more or less.
//
// NDouble dc = d.copy();
// NInt ic = i.copy();
//
// These two 'copy' forms work, but we end with plain NNumbers
//
NNumber dc = d.copy();
NNumber ic = i.copy();
//
// The real problem is that there is no way to recover the
// original NInt or NDouble objects, even when you try
// to use the plain and natural C++ dynamic_cast operations,
// since they fail:
//
NDouble ddc = virtual_poly.NDouble_dynamic_cast(dc);
NInt idc = virtual_poly.NInt_dynamic_cast(dc);
}
}

View file

@ -0,0 +1,19 @@
import virtual_poly
d = virtual_poly.NDouble(3.5)
i = virtual_poly.NInt(2)
dc = d.copy()
ic = i.copy()
if d.get() != dc.get():
raise RuntimeError
if i.get() != ic.get():
raise RuntimeError
ddc = virtual_poly.NDouble_dynamic_cast(dc)
if d.get() != ddc.get():
raise RuntimeError

View file

@ -0,0 +1,109 @@
%module virtual_poly
%inline %{
struct NNumber
{
virtual ~NNumber() {};
virtual NNumber* copy() const = 0;
};
/*
NInt and NDouble are both NNumber derivated classes, but they
have more different than common attributes.
In particular the function 'get', that is type dependent, can't
be included in the NNumber abstract interface.
For this reason, the virtual 'copy' function has a polymorphic
return type, since in most of the cases we don't want to lost the
original object type, which is very very important.
Using the polymorphic return type reduced greatly the need of
using 'dynamic_cast' at the C++ side, and at the target languages
that support it. Python is a target language that support
this feature, Java and Csharp don't.
*/
struct NInt : NNumber
{
NInt(int v) : val(v)
{
}
int get() const
{
return val;
}
virtual NInt* copy() const
{
return new NInt(val);
}
private:
int val;
};
struct NDouble : NNumber
{
NDouble(double v) : val(v)
{
}
double get() const
{
return val;
}
virtual NDouble* copy() const
{
return new NDouble(val);
}
private:
double val;
};
/*
Java (and csharp) can not support the polymorphic return type for
'copy'. So, it just emit 'plain' copy functions for all the cases:
NNumber* NNumber::copy() const;
NNumber* NInt::copy() const;
NNumber* NDouble::copy() const;
In the last two cases, the original 'NInt' and 'NDouble' return
types are lost in the target side. This seems to be a restriction
of the language (strongly typed and 'by value' oriented), and
there is not much that can be done to work it around.
However, to improve the situation, and to be able to recover the
original data types, we try adding 'dynamic_cast' interfaces in
the target language sides. This is a natural mechanism since is
exactly the same you will do in the C++ side if is needed.
*/
inline NInt* NInt_dynamic_cast(NNumber* n) {
return dynamic_cast<NInt*>(n);
}
inline NDouble* NDouble_dynamic_cast(NNumber* n) {
return dynamic_cast<NDouble*>(n);
}
/*
but they don't work either in Java (see the
java/virtual_poly_runme.java file), because of the current way
polymorphic types are wrapped. Using the wrapping method employed
with directors (which are also polymorphic types) should allows
to use the C++ dynamic_cast and recover the original types at the
Java side. And to do that, it is necessary to identify which
classes are polymorphic (the "polymorphic" attribute does that)
and apply the proper wrapping mechanism.
The dynamic_cast interfaces added to this module, currently work
great in languages like python, but in there the polymorphic
return type also works, so, you are not forced to use them as a
fixing mechanism (see the python/virtual_poly_runme.py file).
*/
%}