Discussion:
Abstract base classes to interfaces conversion
Vladimir Kalinin
2013-03-19 22:26:24 UTC
Permalink
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)

I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)

Maybe there is some alternative solution being worked at in some SWIG branch?

If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).

I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.

Any suggestions, advices?
William S Fulton
2013-03-21 08:23:52 UTC
Permalink
Post by Vladimir Kalinin
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
No solution is being currently worked on. The project is one of the GSoC
ideas:
https://github.com/swig/swig/wiki/GSoC-2013-ideas#wiki-Better_Multiple_Inheritance_Support,
but I will remove it if you are going to tackle it.
Post by Vladimir Kalinin
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I'd be very happy if you did, it will be a welcome enhancement to SWIG.
Post by Vladimir Kalinin
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Yes, this is what I asked him to do.
Post by Vladimir Kalinin
Any suggestions, advices?
None other than the obvious - create a new fork on Github and discuss
the development on this list. Are you able to fork it from master rather
than your nested branch?

I don't recall if there were some use cases that Zhiyang did or not.
Looking at those or writing them might help focus on any potential
problems. I think the main challenge is how other wrappers that use a
class that is marked as "feature:interface" is returned from a wrapped
C++ method. I think it requires some additional typemaps for a user to
write/utilise. So some standard solutions for this problem need to be
documented. As "feature:interface" will be explicitly defined by a user,
it is okay, if they have to provide additional customisations in order
for code to compile and work.

William
Vladimir Kalinin
2013-03-21 11:00:17 UTC
Permalink
Post by William S Fulton
Post by Vladimir Kalinin
Any suggestions, advices?
None other than the obvious - create a new fork on Github and discuss
the development on this list. Are you able to fork it from master rather
than your nested branch?
I don't recall if there were some use cases that Zhiyang did or not.
Looking at those or writing them might help focus on any potential
problems. I think the main challenge is how other wrappers that use a
class that is marked as "feature:interface" is returned from a wrapped
C++ method. I think it requires some additional typemaps for a user to
write/utilise. So some standard solutions for this problem need to be
documented. As "feature:interface" will be explicitly defined by a user,
it is okay, if they have to provide additional customisations in order
for code to compile and work.
Ok, I'll make a separate branch for that feature (and a third branch with all new
features merged, to test it in our project)

For returning the interface class from the method there will be used
a derived non-abstract internal class. (That Jiang named
SWIGTYPE##$classname ). That is - from the class marked as "interface"
2 types are derived in the target language - an interface and an
implementation. Implementation class may be marked as "internal" in
C#, it is not intended for client usage.

Of course I cannot yet foresee all the possible complications. Maybe
indeed getCPtr will need to be changed, as Jiang did in his patch.
Vladimir Kalinin
2013-03-21 20:37:30 UTC
Permalink
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
David Piepgrass
2013-03-21 18:46:44 UTC
Permalink
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
hierarchy like:

struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }

It should be possible to create an interface "IB" in C#:

public interface IB {
int b { get; set; }
void fb();
}

But also a concrete class "B" that implements IB:

public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}

And then the wrapper for C would be:

public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}

This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.

It would also be nice if there were some way to request SWIG to create a
property that returns a wrapper for B, e.g. in C#, C could have an
operator for this:

// C can convert to B implicitly
public static implicit operator B(C c) { ??? }

But this feature is optional, since the user could add the necessary code
manually, or (I assume) with help from a macro.




From: Vladimir Kalinin <***@opendesign.com>
To: <swig-***@lists.sourceforge.net>
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces
conversion



As far as I know, currently there is no easy way to convert C++ abstract
base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)

I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)

Maybe there is some alternative solution being worked at in some SWIG
branch?

If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).

I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.

Any suggestions, advices?
Vladimir Kalinin
2013-03-22 19:23:37 UTC
Permalink
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
David Piepgrass
2013-03-26 19:01:23 UTC
Permalink
I suppose that's true for Java, but in C# you could use the same name in
all the interfaces, I think, thanks to explicit interface implementation:

interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}

Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();

Explicit interface implementations have the advantage that they are less
visible (interface methods are always public, technically, but they are
invisible on an object of type "Foo" until you cast to IA or IB or IC.)

Note that since these methods are public, there is greater reason to make
it possible to rename them (it is very annoying that opaque pointers are
hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would
cause an opaque pointer to be produced, or map opaque pointers to IntPtr
instead, through typemaps.)



From: Vladimir Kalinin <***@opendesign.com>
To: David Piepgrass <***@trapezegroup.com>
Cc: <swig-***@lists.sourceforge.net>
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces
conversion



Thinking some more about the subject, it turns out that the only reliable
way to obtain valid C pointer from the interface is to extend the
interface with the corresponding function (like "internal IntPtr
getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements
several interfaces, it has to implement several "getCPtr" functions.
Interface name may be appended|prepended to the function name to
distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()

-----Original Message-----
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
hierarchy like:

struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }

It should be possible to create an interface "IB" in C#:

public interface IB {
int b { get; set; }
void fb();
}

But also a concrete class "B" that implements IB:

public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}

And then the wrapper for C would be:

public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}

This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.

It would also be nice if there were some way to request SWIG to create a
property that returns a wrapper for B, e.g. in C#, C could have an
operator for this:

// C can convert to B implicitly
public static implicit operator B(C c) { ??? }

But this feature is optional, since the user could add the necessary code
manually, or (I assume) with help from a macro.




From: Vladimir Kalinin <***@opendesign.com>
To: <swig-***@lists.sourceforge.net>
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces
conversion




As far as I know, currently there is no easy way to convert C++ abstract
base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)

I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)

Maybe there is some alternative solution being worked at in some SWIG
branch?

If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).

I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.

Any suggestions, advices?


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
Swig-devel mailing list
Swig-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/swig-devel

÷ ÜÔÏÍ ÓÏÏÂÝÅÎÉÉ ×ÉÒÕÓÙ ÎÅ ÏÂÎÁÒÕÖÅÎÙ.
ðÒÏ×ÅÒÅÎÏ AVG - www.avg.com
÷ÅÒÓÉÑ: 2012.0.2240 / ÷ÉÒÕÓÎÁÑ ÂÁÚÁ ÄÁÎÎÙÈ: 2641/5694 - äÁÔÁ ×ÙÐÕÓËÁ:
21.03.2013
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
Swig-devel mailing list
Swig-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/swig-devel
Vladimir Kalinin
2013-04-16 20:10:44 UTC
Permalink
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces

It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them

%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef

%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef

%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.

I attached the sample file I used for testing.

-----Original Message-----
I suppose that's true for Java, but in C# you could use the same name in all the interfaces, I think, thanks to explicit interface implementation:

interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}

Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();

Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)

Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)



From: Vladimir Kalinin <***@opendesign.com>
To: David Piepgrass <***@trapezegroup.com>
Cc: <swig-***@lists.sourceforge.net>
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion




Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()

-----Original Message-----
I have one suggestion about interface support, if you implement this feature: it should be possible to wrap a class with BOTH a normal wrapper AND an interface. That is, don't limit interfaces to abstract base classes--also allow non-abstract base classes. For example, given a class hierarchy like:

struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }

It should be possible to create an interface "IB" in C#:

public interface IB {
int b { get; set; }
void fb();
}

But also a concrete class "B" that implements IB:

public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}

And then the wrapper for C would be:

public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}

This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.

It would also be nice if there were some way to request SWIG to create a property that returns a wrapper for B, e.g. in C#, C could have an operator for this:

// C can convert to B implicitly
public static implicit operator B(C c) { ??? }

But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.




From: Vladimir Kalinin <***@opendesign.com>
To: <swig-***@lists.sourceforge.net>
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion





As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)

I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)

Maybe there is some alternative solution being worked at in some SWIG branch?

If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).

I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.

Any suggestions, advices?


------------------------------------------------------------------------------
William S Fulton
2013-04-19 18:19:35 UTC
Permalink
Hi Vladimir

Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?

BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.

William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
Vladimir Kalinin
2013-04-21 18:14:22 UTC
Permalink
Hi William,

Thanks for the test, I quite forgot about it. It revealed a case
that I didn't think about. Consider the following scenario:
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};

Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)

What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.

Any other suggestions?

BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.

-----Original Message-----
Hi Vladimir

Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?

BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.

William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
Brant K. Kyser
2013-05-16 15:09:08 UTC
Permalink
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?

Once this is working in the C# module, I would also be interested in
porting it over to the Java module.

Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
Vladimir Kalinin
2013-05-16 15:39:14 UTC
Permalink
Hi Brant,

No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.

BTW, what do you think about the questions discussed in the previous
mail?

Best regards,
Vladimir mailto:***@opendesign.com

----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?

Once this is working in the C# module, I would also be interested in
porting it over to the Java module.

Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
Swig-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/swig-devel
Brant K. Kyser
2013-05-17 15:12:56 UTC
Permalink
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.

Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.

Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
Vladimir Kalinin
2013-05-29 14:18:34 UTC
Permalink
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
there is also a separate branch with all my patches merged:
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)

There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider then non-priority.

----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.

Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.

Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
William S Fulton
2013-06-18 18:43:41 UTC
Permalink
Hi Kalinin

I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
thoughts:

- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.

My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.

Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?

I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?

William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
Brant K. Kyser
2013-06-18 19:28:45 UTC
Permalink
Post by William S Fulton
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
The use case that I am interested in is using directors. I am primarily
looking to generate abstract Java and C# classes for C++ classes that
have pure virtual methods, where currently swig generates concrete
classes which fail at runtime if one of the methods, which should be
abstract, is called.

Brant
Vladimir Kalinin
2013-06-18 19:57:21 UTC
Permalink
Hi William,

The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.

Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.

Best regards,
Vladimir mailto:***@opendesign.com

----- Original Message -----
Hi Kalinin

I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
thoughts:

- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.

My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.

Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?

I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?

William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
William S Fulton
2013-06-25 22:31:11 UTC
Permalink
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.

The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.

With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.

I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
the actual interface as an inner class. So for example, if we have:

%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)

struct IA {
virtual void a() = 0;
virtual ~IA() {}
};

IA.java is the only proxy file class generated and SWIGYPE_IA simply
moves into the IA interface:

public interface IA {
long IA_getCPtr();
void a();

public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;

public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}

protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}

protected void finalize() {
delete();
}

public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }

public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}

}
}

but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.

I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.

C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?

Any thoughts or further refinements?

William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
Vladimir Kalinin
2013-07-08 13:41:18 UTC
Permalink
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)

It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.

Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.

Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).

----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.

The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.

With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.

I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
the actual interface as an inner class. So for example, if we have:

%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)

struct IA {
virtual void a() = 0;
virtual ~IA() {}
};

IA.java is the only proxy file class generated and SWIGYPE_IA simply
moves into the IA interface:

public interface IA {
long IA_getCPtr();
void a();

public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;

public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}

protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}

protected void finalize() {
delete();
}

public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }

public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}

}
}

but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.

I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.

C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?

Any thoughts or further refinements?

William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
William S Fulton
2013-07-12 21:42:44 UTC
Permalink
Vladimir, for C#, yes I would like to minimise the number of files and
filename clashes and keep the code for a proxy class together in one
place so it is less scattered about and a bit more consistent with the
new Java approach of putting the same code in the one file.

Thanks for putting in the changes when you get a chance.

William
Post by Vladimir Kalinin
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)
It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.
Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.
Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).
----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.
The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.
With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.
I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)
struct IA {
virtual void a() = 0;
virtual ~IA() {}
};
IA.java is the only proxy file class generated and SWIGYPE_IA simply
public interface IA {
long IA_getCPtr();
void a();
public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;
public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }
public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}
}
}
but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.
I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.
C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?
Any thoughts or further refinements?
William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
William S Fulton
2016-02-04 18:34:03 UTC
Permalink
Hi Vladimir

I need to get some multiple inheritance support working fairly quickly
and was thinking of using this as a starting point. This is quite an
old email chain, but is
https://github.com/wkalinin/swig/tree/interfaces the latest you have
on this? If not, can you describe what else has changed and add on any
additions you'd like to keep into this branch in your repo and I'll
use this as a base for improvements?

Thanks
William
Post by William S Fulton
Vladimir, for C#, yes I would like to minimise the number of files and
filename clashes and keep the code for a proxy class together in one place
so it is less scattered about and a bit more consistent with the new Java
approach of putting the same code in the one file.
Thanks for putting in the changes when you get a chance.
William
Post by Vladimir Kalinin
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)
It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.
Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.
Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).
----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.
The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.
With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.
I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)
struct IA {
virtual void a() = 0;
virtual ~IA() {}
};
IA.java is the only proxy file class generated and SWIGYPE_IA simply
public interface IA {
long IA_getCPtr();
void a();
public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;
public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }
public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}
}
}
but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.
I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.
C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?
Any thoughts or further refinements?
William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider
then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
I suppose that's true for Java, but in C# you could use the same name
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are
less visible (interface methods are always public, technically, but they are
invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to
make it possible to rename them (it is very annoying that opaque pointers
are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that
would cause an opaque pointer to be produced, or map opaque pointers to
IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only
reliable way to obtain valid C pointer from the interface is to extend the
interface with the corresponding function (like "internal IntPtr getCPtr();"
).
It cannot be called just getCPtr(), because if some class implements
several interfaces, it has to implement several "getCPtr" functions.
Interface name may be appended|prepended to the function name to distinguish
them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.
It would also be nice if there were some way to request SWIG to
create a property that returns a wrapper for B, e.g. in C#, C could have an
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary
code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
William S Fulton
2016-02-04 19:41:18 UTC
Permalink
Hi Vladimir

I don't really want to have to analyse your main branch and pull out
these specific changes. You could help by using some of the git diff
commands comparing to whatever version you branched off to pull out
the interface specific changes. Then add them onto your interfaces
branch or setup a new branch from latest master. In the meantime, I'm
getting familiar with what you've done on that branch.

William
Post by Vladimir Kalinin
Hi William,
The actual version we are using locally is here: https://github.com/wkalinin/swig/tree/devel
Unfortunately I don't remember if all the changes from it were merged
in the "interfaces" branch (probably not). I effectively stopped working on that
feature because in its current state it works for us, but to make it
really universal requires much more work than is already done, and I
can't afford it atm.
If you are intending to make it acceptable for the merge in the trunk
that would be wonderful, because we won't have to support the branched
version of swig internally, and I'll be glad to help you in that work.
https://github.com/wkalinin/swig/tree/devel/Lib/csharp/feature_interface.i
The most used macro "DECLARE_INTERFACE_RENAME" is named somewhat
confusingly, but I don't know how to name it better.
Best regards,
-----Original Message-----
Hi Vladimir
I need to get some multiple inheritance support working fairly quickly
and was thinking of using this as a starting point. This is quite an
old email chain, but is
https://github.com/wkalinin/swig/tree/interfaces the latest you have
on this? If not, can you describe what else has changed and add on any
additions you'd like to keep into this branch in your repo and I'll
use this as a base for improvements?
Thanks
William
Post by William S Fulton
Vladimir, for C#, yes I would like to minimise the number of files and
filename clashes and keep the code for a proxy class together in one place
so it is less scattered about and a bit more consistent with the new Java
approach of putting the same code in the one file.
Thanks for putting in the changes when you get a chance.
William
Post by Vladimir Kalinin
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)
It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.
Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.
Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).
----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.
The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.
With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.
I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)
struct IA {
virtual void a() = 0;
virtual ~IA() {}
};
IA.java is the only proxy file class generated and SWIGYPE_IA simply
public interface IA {
long IA_getCPtr();
void a();
public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;
public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }
public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}
}
}
but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.
I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.
C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?
Any thoughts or further refinements?
William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider
then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
I suppose that's true for Java, but in C# you could use the same name
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are
less visible (interface methods are always public, technically, but they are
invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to
make it possible to rename them (it is very annoying that opaque pointers
are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that
would cause an opaque pointer to be produced, or map opaque pointers to
IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces
conversion
Thinking some more about the subject, it turns out that the only
reliable way to obtain valid C pointer from the interface is to extend the
interface with the corresponding function (like "internal IntPtr getCPtr();"
).
It cannot be called just getCPtr(), because if some class implements
several interfaces, it has to implement several "getCPtr" functions.
Interface name may be appended|prepended to the function name to distinguish
them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.
It would also be nice if there were some way to request SWIG to
create a property that returns a wrapper for B, e.g. in C#, C could have an
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary
code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
Vladimir Kalinin
2016-02-04 22:39:26 UTC
Permalink
Hi William,

I tried to merge the missing changes from 'devel' to 'interfaces' and
failed. I will attempt to apply interface related changes to the
master instead, but not today already.

As for analyzing the changes, there are effectively 2 sets of changes
in 'devel', differentiating it from 'swig/master'. These are merges
from 'vadz/doxygen' branch, with my C# comments translation added, and
feature_interface implementation. So you can just compare
Modules/csharp.cxx and Modules/java.cxx with their 'swig/master'
counterparts, and disregard all the changes starting with any string
containing "doxygen".
(There is also L"" literals support not merged to master,
but is does not affect charp.cxx or java.cxx)
I understand that the history looks messy, but that is mostly a result
of multiple merges from/to the master branch.

Best regards,
Vladimir mailto:***@opendesign.com

-----Original Message-----
Hi Vladimir

I don't really want to have to analyse your main branch and pull out
these specific changes. You could help by using some of the git diff
commands comparing to whatever version you branched off to pull out
the interface specific changes. Then add them onto your interfaces
branch or setup a new branch from latest master. In the meantime, I'm
getting familiar with what you've done on that branch.

William
Post by Vladimir Kalinin
Hi William,
The actual version we are using locally is here: https://github.com/wkalinin/swig/tree/devel
Unfortunately I don't remember if all the changes from it were merged
in the "interfaces" branch (probably not). I effectively stopped working on that
feature because in its current state it works for us, but to make it
really universal requires much more work than is already done, and I
can't afford it atm.
If you are intending to make it acceptable for the merge in the trunk
that would be wonderful, because we won't have to support the branched
version of swig internally, and I'll be glad to help you in that work.
https://github.com/wkalinin/swig/tree/devel/Lib/csharp/feature_interface.i
The most used macro "DECLARE_INTERFACE_RENAME" is named somewhat
confusingly, but I don't know how to name it better.
Best regards,
-----Original Message-----
Hi Vladimir
I need to get some multiple inheritance support working fairly quickly
and was thinking of using this as a starting point. This is quite an
old email chain, but is
https://github.com/wkalinin/swig/tree/interfaces the latest you have
on this? If not, can you describe what else has changed and add on any
additions you'd like to keep into this branch in your repo and I'll
use this as a base for improvements?
Thanks
William
Post by William S Fulton
Vladimir, for C#, yes I would like to minimise the number of files and
filename clashes and keep the code for a proxy class together in one place
so it is less scattered about and a bit more consistent with the new Java
approach of putting the same code in the one file.
Thanks for putting in the changes when you get a chance.
William
Post by Vladimir Kalinin
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)
It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.
Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.
Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).
----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.
The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.
With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.
I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)
struct IA {
virtual void a() = 0;
virtual ~IA() {}
};
IA.java is the only proxy file class generated and SWIGYPE_IA simply
public interface IA {
long IA_getCPtr();
void a();
public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;
public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }
public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}
}
}
but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.
I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.
C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?
Any thoughts or further refinements?
William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider
then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
I suppose that's true for Java, but in C# you could use the same name
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are
less visible (interface methods are always public, technically, but they are
invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to
make it possible to rename them (it is very annoying that opaque pointers
are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that
would cause an opaque pointer to be produced, or map opaque pointers to
IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces
conversion
Thinking some more about the subject, it turns out that the only
reliable way to obtain valid C pointer from the interface is to extend the
interface with the corresponding function (like "internal IntPtr getCPtr();"
).
It cannot be called just getCPtr(), because if some class implements
several interfaces, it has to implement several "getCPtr" functions.
Interface name may be appended|prepended to the function name to distinguish
them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.
It would also be nice if there were some way to request SWIG to
create a property that returns a wrapper for B, e.g. in C#, C could have an
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary
code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
Paul Donohue
2016-02-10 16:20:44 UTC
Permalink
I'm not sure what your timeline is here, but I too have a need to get multiple inheritance support working, and a couple months ago I spent a bunch of time analyzing Vladamir's changes and thinking through various use cases. I conceptually broke the problem up into a series of smaller changes, which I then started documenting and implementing (based loosely on Vladamir's changes, but with various significant improvements). Unfortunately, other priorities interrupted my work, so both my documentation and implementation are still incomplete and rather messy. However, if it would help you, I can try to revisit this over the next few days and see if I can't finish some of it. (I intended to pick this project back up soon anyway.)

Basically, the series of changes is:
1) Allow access to base class members without explicit C++ upcasts by copying the members of any base class that is skipped by the language module (due to a lack of support for multiple inheritance) to the derived class.
2) Add target language support for implicit upcasts to abstract base classes by:
2a) Converting abstract base classes into interfaces in the target language
2b) Generating additional proxy classes that implement each interface so that base class objects returned by C++ functions can be returned in the target language.
2c) Automatically detecting abstract base classes and enabling 2a and 2b when appropriate.
3) Add support for multiple concrete base classes by:
3a) Exposing the base proxy classes generated by #2 so they can be instantiated directly.
3b) Adjusting swig so that generated functions in the target language which return the base class will explicitly return the base proxy class in the target language (rather than returning a base proxy class object that is cast to the associated interface in the target language), but generated functions in the target language which accept the base class as an argument will still use the interface rather than the base proxy class as the argument type so that both concrete base objects and derived objects can be passed in. (This would be optional behavior that could be selectively enabled/disabled depending on the use case.)
4) Assorted minor tweaks to ensure that downcasts in the target language work as expected by default and to enable some use of directors with multiple inheritance. (I had several ideas here, but I hadn't figured out all of the use cases for this yet, so I hadn't decided whether any of these ideas actually made sense and were worth implementing.)

-Paul
Post by Vladimir Kalinin
Hi William,
I tried to merge the missing changes from 'devel' to 'interfaces' and
failed. I will attempt to apply interface related changes to the
master instead, but not today already.
As for analyzing the changes, there are effectively 2 sets of changes
in 'devel', differentiating it from 'swig/master'. These are merges
from 'vadz/doxygen' branch, with my C# comments translation added, and
feature_interface implementation. So you can just compare
Modules/csharp.cxx and Modules/java.cxx with their 'swig/master'
counterparts, and disregard all the changes starting with any string
containing "doxygen".
(There is also L"" literals support not merged to master,
but is does not affect charp.cxx or java.cxx)
I understand that the history looks messy, but that is mostly a result
of multiple merges from/to the master branch.
Best regards,
-----Original Message-----
Hi Vladimir
I don't really want to have to analyse your main branch and pull out
these specific changes. You could help by using some of the git diff
commands comparing to whatever version you branched off to pull out
the interface specific changes. Then add them onto your interfaces
branch or setup a new branch from latest master. In the meantime, I'm
getting familiar with what you've done on that branch.
William
Post by Vladimir Kalinin
Hi William,
The actual version we are using locally is here: https://github.com/wkalinin/swig/tree/devel
Unfortunately I don't remember if all the changes from it were merged
in the "interfaces" branch (probably not). I effectively stopped working on that
feature because in its current state it works for us, but to make it
really universal requires much more work than is already done, and I
can't afford it atm.
If you are intending to make it acceptable for the merge in the trunk
that would be wonderful, because we won't have to support the branched
version of swig internally, and I'll be glad to help you in that work.
https://github.com/wkalinin/swig/tree/devel/Lib/csharp/feature_interface.i
The most used macro "DECLARE_INTERFACE_RENAME" is named somewhat
confusingly, but I don't know how to name it better.
Best regards,
-----Original Message-----
Hi Vladimir
I need to get some multiple inheritance support working fairly quickly
and was thinking of using this as a starting point. This is quite an
old email chain, but is
https://github.com/wkalinin/swig/tree/interfaces the latest you have
on this? If not, can you describe what else has changed and add on any
additions you'd like to keep into this branch in your repo and I'll
use this as a base for improvements?
Thanks
William
Post by William S Fulton
Vladimir, for C#, yes I would like to minimise the number of files and
filename clashes and keep the code for a proxy class together in one place
so it is less scattered about and a bit more consistent with the new Java
approach of putting the same code in the one file.
Thanks for putting in the changes when you get a chance.
William
Post by Vladimir Kalinin
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)
It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.
Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.
Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).
----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.
The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.
With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.
I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)
struct IA {
virtual void a() = 0;
virtual ~IA() {}
};
IA.java is the only proxy file class generated and SWIGYPE_IA simply
public interface IA {
long IA_getCPtr();
void a();
public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;
public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }
public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}
}
}
but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.
I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.
C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?
Any thoughts or further refinements?
William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires
generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider
then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
I suppose that's true for Java, but in C# you could use the same name
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are
less visible (interface methods are always public, technically, but they are
invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to
make it possible to rename them (it is very annoying that opaque pointers
are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that
would cause an opaque pointer to be produced, or map opaque pointers to
IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces
conversion
Thinking some more about the subject, it turns out that the only
reliable way to obtain valid C pointer from the interface is to extend the
interface with the corresponding function (like "internal IntPtr getCPtr();"
).
It cannot be called just getCPtr(), because if some class implements
several interfaces, it has to implement several "getCPtr" functions.
Interface name may be appended|prepended to the function name to distinguish
them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.
It would also be nice if there were some way to request SWIG to
create a property that returns a wrapper for B, e.g. in C#, C could have an
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary
code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces
conversion
As far as I know, currently there is no easy way to convert C++
abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG
branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for
building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
William S Fulton
2016-02-10 21:55:50 UTC
Permalink
I've been working on this over the last few days. My goal is to get
something useful soon (days rather than weeks). I also think this
should be turned on via typemaps/features and not automatic in the
near term. If we can get good code using this manual approach, we can
start think about turning it on automatically for say swig-3.1.

My focus is on only concrete classes in the inheritance hierarchy and
I havn't had to radically change Vladimir's original approach too much
to achieve that. Perhaps you can focus on fixing the current state for
supporting pure abstract base classes as that is your interest?
Although longer term the generated code needs to be customisable (too
much is hard coded), I'd like to work on getting the correct code
generated in the short term.

I've pushed my modifications to a branch called interfaces:
https://github.com/swig/swig/tree/interfaces
I havn't tried to track down other changes in Vladimir's
https://github.com/wkalinin/swig/tree/devel.

I think most of your points are roughly working in the branch via the
DECLARE_INTERFACE_RENAME macro, although I don't exactly understand
all of them. What I suggest is for you to take a look at the
generated code in the branch and discuss what you think should change
and is incorrect in the two test-cases: multiple_inheritance_abstract
and multiple_inheritance_interfaces. These examples need expanding
with further use cases, in particular true abstract base classes and
more multiple inheritance.

For the record, I don't envisage supporting virtual inheritance.

I havn't thought about directors and think we should solve non-directors first.

I am mostly happy with the inheritance hierarchy that is generated as
the multiple_inheritance_interfaces testcase. Although am undecided
whether K should be:

public class K implements IK { ... }
instead of:
public class K implements IJ, IK { ... }

similarly perhaps L and M should only implement IL ??

William
Post by Paul Donohue
I'm not sure what your timeline is here, but I too have a need to get multiple inheritance support working, and a couple months ago I spent a bunch of time analyzing Vladamir's changes and thinking through various use cases. I conceptually broke the problem up into a series of smaller changes, which I then started documenting and implementing (based loosely on Vladamir's changes, but with various significant improvements). Unfortunately, other priorities interrupted my work, so both my documentation and implementation are still incomplete and rather messy. However, if it would help you, I can try to revisit this over the next few days and see if I can't finish some of it. (I intended to pick this project back up soon anyway.)
1) Allow access to base class members without explicit C++ upcasts by copying the members of any base class that is skipped by the language module (due to a lack of support for multiple inheritance) to the derived class.
2a) Converting abstract base classes into interfaces in the target language
2b) Generating additional proxy classes that implement each interface so that base class objects returned by C++ functions can be returned in the target language.
2c) Automatically detecting abstract base classes and enabling 2a and 2b when appropriate.
3a) Exposing the base proxy classes generated by #2 so they can be instantiated directly.
3b) Adjusting swig so that generated functions in the target language which return the base class will explicitly return the base proxy class in the target language (rather than returning a base proxy class object that is cast to the associated interface in the target language), but generated functions in the target language which accept the base class as an argument will still use the interface rather than the base proxy class as the argument type so that both concrete base objects and derived objects can be passed in. (This would be optional behavior that could be selectively enabled/disabled depending on the use case.)
4) Assorted minor tweaks to ensure that downcasts in the target language work as expected by default and to enable some use of directors with multiple inheritance. (I had several ideas here, but I hadn't figured out all of the use cases for this yet, so I hadn't decided whether any of these ideas actually made sense and were worth implementing.)
-Paul
Post by Vladimir Kalinin
Hi William,
I tried to merge the missing changes from 'devel' to 'interfaces' and
failed. I will attempt to apply interface related changes to the
master instead, but not today already.
As for analyzing the changes, there are effectively 2 sets of changes
in 'devel', differentiating it from 'swig/master'. These are merges
from 'vadz/doxygen' branch, with my C# comments translation added, and
feature_interface implementation. So you can just compare
Modules/csharp.cxx and Modules/java.cxx with their 'swig/master'
counterparts, and disregard all the changes starting with any string
containing "doxygen".
(There is also L"" literals support not merged to master,
but is does not affect charp.cxx or java.cxx)
I understand that the history looks messy, but that is mostly a result
of multiple merges from/to the master branch.
Best regards,
-----Original Message-----
Hi Vladimir
I don't really want to have to analyse your main branch and pull out
these specific changes. You could help by using some of the git diff
commands comparing to whatever version you branched off to pull out
the interface specific changes. Then add them onto your interfaces
branch or setup a new branch from latest master. In the meantime, I'm
getting familiar with what you've done on that branch.
William
Post by Vladimir Kalinin
Hi William,
The actual version we are using locally is here: https://github.com/wkalinin/swig/tree/devel
Unfortunately I don't remember if all the changes from it were merged
in the "interfaces" branch (probably not). I effectively stopped working on that
feature because in its current state it works for us, but to make it
really universal requires much more work than is already done, and I
can't afford it atm.
If you are intending to make it acceptable for the merge in the trunk
that would be wonderful, because we won't have to support the branched
version of swig internally, and I'll be glad to help you in that work.
https://github.com/wkalinin/swig/tree/devel/Lib/csharp/feature_interface.i
The most used macro "DECLARE_INTERFACE_RENAME" is named somewhat
confusingly, but I don't know how to name it better.
Best regards,
-----Original Message-----
Hi Vladimir
I need to get some multiple inheritance support working fairly quickly
and was thinking of using this as a starting point. This is quite an
old email chain, but is
https://github.com/wkalinin/swig/tree/interfaces the latest you have
on this? If not, can you describe what else has changed and add on any
additions you'd like to keep into this branch in your repo and I'll
use this as a base for improvements?
Thanks
William
Post by William S Fulton
Vladimir, for C#, yes I would like to minimise the number of files and
filename clashes and keep the code for a proxy class together in one place
so it is less scattered about and a bit more consistent with the new Java
approach of putting the same code in the one file.
Thanks for putting in the changes when you get a chance.
William
Post by Vladimir Kalinin
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)
It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.
Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.
Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).
----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.
The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.
With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.
I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)
struct IA {
virtual void a() = 0;
virtual ~IA() {}
};
IA.java is the only proxy file class generated and SWIGYPE_IA simply
public interface IA {
long IA_getCPtr();
void a();
public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;
public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }
public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}
}
}
but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.
I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.
C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?
Any thoughts or further refinements?
William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires
generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider
then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't
want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in
ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for
now)
https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
I suppose that's true for Java, but in C# you could use the same name
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are
less visible (interface methods are always public, technically, but they are
invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to
make it possible to rename them (it is very annoying that opaque pointers
are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that
would cause an opaque pointer to be produced, or map opaque pointers to
IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces
conversion
Thinking some more about the subject, it turns out that the only
reliable way to obtain valid C pointer from the interface is to extend the
interface with the corresponding function (like "internal IntPtr getCPtr();"
).
It cannot be called just getCPtr(), because if some class implements
several interfaces, it has to implement several "getCPtr" functions.
Interface name may be appended|prepended to the function name to distinguish
them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.
It would also be nice if there were some way to request SWIG to
create a property that returns a wrapper for B, e.g. in C#, C could have an
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary
code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces
conversion
As far as I know, currently there is no easy way to convert C++
abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG
branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for
building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for
building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
Vladimir Kalinin
2016-02-10 23:34:44 UTC
Permalink
Hi William,

I see you've already extracted all the relevant changes in your
branch. Looks like not much was done in my 'devel' branch after
'interfaces' was abandoned. There is one somewhat related change:
SHA-1: e4de42337d579d7f83a4d91925a13169708f0b77
SHA-1: 51d9fe1e0250dcb5d6d4fd2c46f0545f9e7ea3b5
That fixes 'override' for C#, but it may be separated as a distinct
PR, because it is useful even w/o feature:interface. It is enough to
just have multiple inheritance in C++ code for the 'override' to break.

Also there is a small fix for director generation
SHA-1: 67afe4005f6848b00976810fcff80f2fb494f2d9

And there is unfinished feature:abstract implementation in
SHA-1: dfbdd5f7b0a7512397a05a77c6e7a7ca6829c993
SHA-1: 50c4bbcfdb90220c06da04bc6cd7b100b1ad255a
SHA-1: 75a80b0f75bd76cf7d0c569168ab3612ffc39d1e
Now, this feature, although theoretically cool, I'm not sure if it is of much use.
It's been 3 years since we published our library interfaces in C# and
Java, and we have a lot of users, but I got zero requests for real
interfaces in place of our pure abstract classes.

I agree that there is a lot of stuff hardcoded, that should normally
be customizable, but w/o much real world use cases it is hard to tell
what exactly should be customized and how.

Sorry for being of no help, this week was unusually busy. And thanks
for your work on the test suite and further improvements.

Best regards,
Vladimir mailto:***@opendesign.com

-----Original Message-----
I've been working on this over the last few days. My goal is to get
something useful soon (days rather than weeks). I also think this
should be turned on via typemaps/features and not automatic in the
near term. If we can get good code using this manual approach, we can
start think about turning it on automatically for say swig-3.1.

My focus is on only concrete classes in the inheritance hierarchy and
I havn't had to radically change Vladimir's original approach too much
to achieve that. Perhaps you can focus on fixing the current state for
supporting pure abstract base classes as that is your interest?
Although longer term the generated code needs to be customisable (too
much is hard coded), I'd like to work on getting the correct code
generated in the short term.

I've pushed my modifications to a branch called interfaces:
https://github.com/swig/swig/tree/interfaces
I havn't tried to track down other changes in Vladimir's
https://github.com/wkalinin/swig/tree/devel.

I think most of your points are roughly working in the branch via the
DECLARE_INTERFACE_RENAME macro, although I don't exactly understand
all of them. What I suggest is for you to take a look at the
generated code in the branch and discuss what you think should change
and is incorrect in the two test-cases: multiple_inheritance_abstract
and multiple_inheritance_interfaces. These examples need expanding
with further use cases, in particular true abstract base classes and
more multiple inheritance.

For the record, I don't envisage supporting virtual inheritance.

I havn't thought about directors and think we should solve non-directors first.

I am mostly happy with the inheritance hierarchy that is generated as
the multiple_inheritance_interfaces testcase. Although am undecided
whether K should be:

public class K implements IK { ... }
instead of:
public class K implements IJ, IK { ... }

similarly perhaps L and M should only implement IL ??

William
Post by Paul Donohue
I'm not sure what your timeline is here, but I too have a need to get multiple inheritance support working, and a couple months ago I spent a bunch of time analyzing Vladamir's changes and thinking through various use cases. I conceptually broke the problem up into a series of smaller changes, which I then started documenting and implementing (based loosely on Vladamir's changes, but with various significant improvements). Unfortunately, other priorities interrupted my work, so both my documentation and implementation are still incomplete and rather messy. However, if it would help you, I can try to revisit this over the next few days and see if I can't finish some of it. (I intended to pick this project back up soon anyway.)
1) Allow access to base class members without explicit C++ upcasts by copying the members of any base class that is skipped by the language module (due to a lack of support for multiple inheritance) to the derived class.
2a) Converting abstract base classes into interfaces in the target language
2b) Generating additional proxy classes that implement each interface so that base class objects returned by C++ functions can be returned in the target language.
2c) Automatically detecting abstract base classes and enabling 2a and 2b when appropriate.
3a) Exposing the base proxy classes generated by #2 so they can be instantiated directly.
3b) Adjusting swig so that generated functions in the target language which return the base class will explicitly return the base proxy class in the target language (rather than returning a base proxy class object that is cast to the associated interface in the target language), but generated functions in the target language which accept the base class as an argument will still use the interface rather than the base proxy class as the argument type so that both concrete base objects and derived objects can be passed in. (This would be optional behavior that could be selectively enabled/disabled depending on the use case.)
4) Assorted minor tweaks to ensure that downcasts in the target language work as expected by default and to enable some use of directors with multiple inheritance. (I had several ideas here, but I hadn't figured out all of the use cases for this yet, so I hadn't decided whether any of these ideas actually made sense and were worth implementing.)
-Paul
Post by Vladimir Kalinin
Hi William,
I tried to merge the missing changes from 'devel' to 'interfaces' and
failed. I will attempt to apply interface related changes to the
master instead, but not today already.
As for analyzing the changes, there are effectively 2 sets of changes
in 'devel', differentiating it from 'swig/master'. These are merges
from 'vadz/doxygen' branch, with my C# comments translation added, and
feature_interface implementation. So you can just compare
Modules/csharp.cxx and Modules/java.cxx with their 'swig/master'
counterparts, and disregard all the changes starting with any string
containing "doxygen".
(There is also L"" literals support not merged to master,
but is does not affect charp.cxx or java.cxx)
I understand that the history looks messy, but that is mostly a result
of multiple merges from/to the master branch.
Best regards,
-----Original Message-----
Hi Vladimir
I don't really want to have to analyse your main branch and pull out
these specific changes. You could help by using some of the git diff
commands comparing to whatever version you branched off to pull out
the interface specific changes. Then add them onto your interfaces
branch or setup a new branch from latest master. In the meantime, I'm
getting familiar with what you've done on that branch.
William
Post by Vladimir Kalinin
Hi William,
The actual version we are using locally is here: https://github.com/wkalinin/swig/tree/devel
Unfortunately I don't remember if all the changes from it were merged
in the "interfaces" branch (probably not). I effectively stopped working on that
feature because in its current state it works for us, but to make it
really universal requires much more work than is already done, and I
can't afford it atm.
If you are intending to make it acceptable for the merge in the trunk
that would be wonderful, because we won't have to support the branched
version of swig internally, and I'll be glad to help you in that work.
https://github.com/wkalinin/swig/tree/devel/Lib/csharp/feature_interface.i
The most used macro "DECLARE_INTERFACE_RENAME" is named somewhat
confusingly, but I don't know how to name it better.
Best regards,
-----Original Message-----
Hi Vladimir
I need to get some multiple inheritance support working fairly quickly
and was thinking of using this as a starting point. This is quite an
old email chain, but is
https://github.com/wkalinin/swig/tree/interfaces the latest you have
on this? If not, can you describe what else has changed and add on any
additions you'd like to keep into this branch in your repo and I'll
use this as a base for improvements?
Thanks
William
Post by William S Fulton
Vladimir, for C#, yes I would like to minimise the number of files and
filename clashes and keep the code for a proxy class together in one place
so it is less scattered about and a bit more consistent with the new Java
approach of putting the same code in the one file.
Thanks for putting in the changes when you get a chance.
William
Post by Vladimir Kalinin
Hiding the implementation class within the Java interface is a good idea.
I'll implement it as soon as I'll have time. (perhaps at the end of the
month; unfortunately, I'm quite busy right now.)
It is impossible to completely hide the implementation class from
the user, because if the user wants to implement the interface on the
Java/C# side he will need to aggregate the implementation class,
to have a valid underlying C++ class for the interface.
Non-const ref appeared in the typemaps because in our project some
interface was returned via non-const reference. Anyway, typemaps are
customizable, we'll just use the modified version if the standard will
be changed.
Moving C# implementation class in a separate namespace gives no
benefit regarding name space pollution - this namespace
should have a unique name anyway. It is possible to move it in the
same file of course (can't see why does it matter though - to minimize
the number of files?).
----- Original Message -----
I've taken another look at the implementation. My opinions were mostly
based on having this SWIGTYPE_xxx class exposed to the user. It looks
like that is not the intention and what I see is just a bug.
The typemaps in feature_java.i need to be changed for non-const ref,
otherwise the SWIGTYPE_xxx classes appear in the API that a user will see.
With this change, the approach is much better. The SWIGTYPE_xxx classes
become an implementation detail which I think is quite acceptable.
I've a suggestion to improve further. First lets give these SWIGTYPE_xxx
classes a name, say Interface Proxy classes. For Java, let's rename all
these classes and call them all SwigInterfaceProxy and push them into
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, IA, SWIGTYPE_IA)
struct IA {
virtual void a() = 0;
virtual ~IA() {}
};
IA.java is the only proxy file class generated and SWIGYPE_IA simply
public interface IA {
long IA_getCPtr();
void a();
public class SWIGTYPE_IA implements IA {
private long swigCPtr;
protected boolean swigCMemOwn;
public SWIGTYPE_IA(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(SWIGTYPE_IA obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_SWIGTYPE_IA(swigCPtr);
}
swigCPtr = 0;
}
}
public long IA_getCPtr(){ return
exampleJNI.SWIGTYPE_IA_IA_getCPtr(swigCPtr); }
public void a() {
exampleJNI.SWIGTYPE_IA_a(swigCPtr);
}
}
}
but then go one step further and rename SWIGTYPE_IA to
SwigInterfaceProxy. That is the inner class has the same name for all
classes that use the 'interface' feature.
I think using the same name, ie, SwigInterfaceProxy, makes the generated
code easier to read/comprehend.
C# doesn't accept inner classes within an interface. I'd like to see the
Interface Proxy generated into the IA.cs file still, so how about
something along the lines of generating it into a different namespace in
IA.cs?
Any thoughts or further refinements?
William
Post by Vladimir Kalinin
Hi William,
The point is to reflect multiple inheritance. All that you say is
true, but what alternative can you suggest?
If you don't have multiple inheritance, clearly you don't need
interfaces.
Anyway, this feature is useful in our project even if will not be
useful for anyone else, so I'll just keep it in my branch.
Best regards,
----- Original Message -----
Hi Kalinin
I've just been looking at the interface implementation. I know I
originally suggested we develop this, but given the restrictions of the
design I am now wondering what the point is! Here is some analysis and
- The target language interface replaces the target language proxy
class, however, a proxy class is still really needed. It is needed to
hold the underlying c++ pointer, although the implementation sort of
tries to avoid this by making a call into c++ from the target language
which has a performance hit compared to holding the pointer on the
target language side. With this approach the proxy class can be avoided
in some uncommon circumstances but the SWIGTYPE_xxx classes need to be
generated to provide the functionality of the removed proxy class.
- The implementation requires that each class in an inheritance chain to
repeat the 'implements' (inheritance) from the interface... this is not
normal. There is no one-to-one mapping made onto the designed C++
inheritance chain, rather confusing and weird.
- There is too much code coming from Swig that is not controllable by
users, eg all of the SWIGTYPE_xxx classes... typemaps can't change this
code because it is a non-existent C++ type. This could be overcome
though by adding in yet more features (complexity).
- Having an interface ABC and a SWIGTYPE_ABC is messy in my point of view.
My current thinking is because the SWIGTYPE_xxx proxy classes are still
needed, all that has happened is the generated code is more confusing
without any gain, in fact there is a performance hit.
Brant, you mentioned two types of interfaces, where developers need to
know which methods to implement. If you are deriving from the proxy
classes, then I presume you are using directors?
I'm not entirely sure what the best way forward is, but I suspect the
only way to have normal interfaces is to turn it on only for directors.
Has anyone looked at that? Maybe I've missed something... what are the
use cases (not using directors) that are useful with the current
implementation of the feature as it stands?
William
Post by Vladimir Kalinin
I "solved" the non-abstract method problem recently and ported
the final implementation to Java.
(see https://github.com/wkalinin/swig/tree/interfaces
https://github.com/wkalinin/swig/tree/devel (with nested classes, etc.)
This is what I myself use in production, so the first version may
contain some merge bugs - it was used only in test environment)
There are still some limitations in complex cases (e.g. when one interface
is inherited several times via different inheritance paths - it requires
generating
corresponding "feature:action" for C++ proxy methods, to make the
calls via correct upcast chain),
but I personally did not yet met these cases in practice and consider
then non-priority.
----- Original Message -----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.
Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.
Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't
want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in
ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for
now)
https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
I suppose that's true for Java, but in C# you could use the same name
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are
less visible (interface methods are always public, technically, but they are
invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to
make it possible to rename them (it is very annoying that opaque pointers
are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that
would cause an opaque pointer to be produced, or map opaque pointers to
IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces
conversion
Thinking some more about the subject, it turns out that the only
reliable way to obtain valid C pointer from the interface is to extend the
interface with the corresponding function (like "internal IntPtr getCPtr();"
).
It cannot be called just getCPtr(), because if some class implements
several interfaces, it has to implement several "getCPtr" functions.
Interface name may be appended|prepended to the function name to distinguish
them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
I have one suggestion about interface support, if you implement this
feature: it should be possible to wrap a class with BOTH a normal wrapper
AND an interface. That is, don't limit interfaces to abstract base
classes--also allow non-abstract base classes. For example, given a class
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of
course, if B is an abstract base class then an interface alone should
suffice, i.e. only an interface IB is needed, not a class B.
It would also be nice if there were some way to request SWIG to
create a property that returns a wrapper for B, e.g. in C#, C could have an
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary
code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces
conversion
As far as I know, currently there is no easy way to convert C++
abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG
branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for
building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for
building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
.
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
William S Fulton
2016-02-12 08:03:07 UTC
Permalink
Post by Vladimir Kalinin
Hi William,
I see you've already extracted all the relevant changes in your
branch. Looks like not much was done in my 'devel' branch after
SHA-1: e4de42337d579d7f83a4d91925a13169708f0b77
SHA-1: 51d9fe1e0250dcb5d6d4fd2c46f0545f9e7ea3b5
That fixes 'override' for C#, but it may be separated as a distinct
PR, because it is useful even w/o feature:interface. It is enough to
just have multiple inheritance in C++ code for the 'override' to break.
I tried applying this one and it didn't fix the
multiple_inheritance_abstract nor multiple_inheritance_interfaces
testcases properly, so more work is needed in this area. My general
thoughts are that we need to support feature:interface in the core and
put in override fixes for C# in allocate.cxx. In a similar area we
also need to support C++11 override and final. If all this gets
sorted, I'd like to add in @Override for Java, I think there is a
patch for this knocking about somewhere.
Post by Vladimir Kalinin
Also there is a small fix for director generation
SHA-1: 67afe4005f6848b00976810fcff80f2fb494f2d9
I've applied this, but didn't test as there are no interface tests for
directors yet.
Post by Vladimir Kalinin
And there is unfinished feature:abstract implementation in
SHA-1: dfbdd5f7b0a7512397a05a77c6e7a7ca6829c993
SHA-1: 50c4bbcfdb90220c06da04bc6cd7b100b1ad255a
SHA-1: 75a80b0f75bd76cf7d0c569168ab3612ffc39d1e
Now, this feature, although theoretically cool, I'm not sure if it is of much use.
It's been 3 years since we published our library interfaces in C# and
Java, and we have a lot of users, but I got zero requests for real
interfaces in place of our pure abstract classes.
I didn't quite follow exactly what this does other than adding in
abstract to the base class. Does it need the interface feature too?
Short example?
Post by Vladimir Kalinin
I agree that there is a lot of stuff hardcoded, that should normally
be customizable, but w/o much real world use cases it is hard to tell
what exactly should be customized and how.
I can sort this out if the general code generation approach is
satisfactory. Am waiting for Paul's feedback on the current state
first.
Post by Vladimir Kalinin
Sorry for being of no help, this week was unusually busy. And thanks
for your work on the test suite and further improvements.
That's okay. If your time is freed up soon, probably the C# override
fixes would be the most useful thing to work on.

I've merged with the latest in master so now the 'interfaces' branch
is up to date with master.

William
Vladimir Kalinin
2016-02-13 08:49:37 UTC
Permalink
Hi William,
Post by William S Fulton
I didn't quite follow exactly what this does other than adding in
abstract to the base class. Does it need the interface feature too?
Short example?
I was myself a little vague about the details after 2 years, but now that
I looked it over, it seems to be completely unrelated to the multiple
inheritance case.
The idea was just to expose abstract methods as abstract in the
director class, so that the implementer would be unable to forget one
of them, and at the same time not to lose the ability to return
interface class with the abstract functions implemented on the C++
side. It was intended to achieve by the same method as for the feature
interface: by splitting proxy class into "abstract" and hidden
"implementation" classes, where "impelmetation" is to be used in the
generated code, and "abstract" may be derived from.
Post by William S Fulton
That's okay. If your time is freed up soon, probably the C# override
fixes would be the most useful thing to work on.
I'll look into it today/tomorrow.

Best regards,
Vladimir mailto:***@opendesign.com

-----Original Message-----
Post by William S Fulton
Hi William,
I see you've already extracted all the relevant changes in your
branch. Looks like not much was done in my 'devel' branch after
SHA-1: e4de42337d579d7f83a4d91925a13169708f0b77
SHA-1: 51d9fe1e0250dcb5d6d4fd2c46f0545f9e7ea3b5
That fixes 'override' for C#, but it may be separated as a distinct
PR, because it is useful even w/o feature:interface. It is enough to
just have multiple inheritance in C++ code for the 'override' to break.
I tried applying this one and it didn't fix the
multiple_inheritance_abstract nor multiple_inheritance_interfaces
testcases properly, so more work is needed in this area. My general
thoughts are that we need to support feature:interface in the core and
put in override fixes for C# in allocate.cxx. In a similar area we
also need to support C++11 override and final. If all this gets
sorted, I'd like to add in @Override for Java, I think there is a
patch for this knocking about somewhere.
Post by William S Fulton
Also there is a small fix for director generation
SHA-1: 67afe4005f6848b00976810fcff80f2fb494f2d9
I've applied this, but didn't test as there are no interface tests for
directors yet.
Post by William S Fulton
And there is unfinished feature:abstract implementation in
SHA-1: dfbdd5f7b0a7512397a05a77c6e7a7ca6829c993
SHA-1: 50c4bbcfdb90220c06da04bc6cd7b100b1ad255a
SHA-1: 75a80b0f75bd76cf7d0c569168ab3612ffc39d1e
Now, this feature, although theoretically cool, I'm not sure if it is of much use.
It's been 3 years since we published our library interfaces in C# and
Java, and we have a lot of users, but I got zero requests for real
interfaces in place of our pure abstract classes.
I didn't quite follow exactly what this does other than adding in
abstract to the base class. Does it need the interface feature too?
Short example?
Post by William S Fulton
I agree that there is a lot of stuff hardcoded, that should normally
be customizable, but w/o much real world use cases it is hard to tell
what exactly should be customized and how.
I can sort this out if the general code generation approach is
satisfactory. Am waiting for Paul's feedback on the current state
first.
Post by William S Fulton
Sorry for being of no help, this week was unusually busy. And thanks
for your work on the test suite and further improvements.
That's okay. If your time is freed up soon, probably the C# override
fixes would be the most useful thing to work on.

I've merged with the latest in master so now the 'interfaces' branch
is up to date with master.

William
William S Fulton
2016-03-04 00:47:36 UTC
Permalink
Post by Vladimir Kalinin
I agree that there is a lot of stuff hardcoded, that should normally
Post by Vladimir Kalinin
be customizable, but w/o much real world use cases it is hard to tell
what exactly should be customized and how.
I can sort this out if the general code generation approach is
satisfactory. Am waiting for Paul's feedback on the current state
first.
Paul, any input?
Post by Vladimir Kalinin
I've merged with the latest in master so now the 'interfaces' branch
is up to date with master.
I've pushed my latest changes to the interfaces branch. There are a few
changes, most notably:

- merged in code from master to the branch
- moved code into typemaps and expanded types supported
- various corner cases fixed and added plenty of testcases
- re-organised the implementation
- added error checking
- added in Java premature garbage collection prevention parameter support
for these interfaces
- support nspace feature and namespaces in general
- renamed original macros and removed the need for providing an interface
name (suggestions for better names are welcome). New macros are:

%interface(TYPE) - leaves proxy class name unchanged and names the
interface with a I prefix
%interface_impl(TYPE) - renames proxy class with SwigImpl suffix and the
interface name is what the proxy class would have been called
%interface_custom(IMPL, INTERFACE, TYPE) - for providing custom proxy and
interface names, eg:

%interface_custom("FooImplementation", "IFoo", MySpace::FooClass)

namespace MySpace {
struct FooClass { ... };
struct DerivedClass : FooClass { ... };
}

results in a Java proxy class called FooImplementation and Java interface
called IFoo. A generic version of this renaming can be obtained with the
%rename encoders. The following will provide the same names as above:

%interface_custom("%(rstrip:[Class])sImplementation",
"I%(regex:/(.*)Implementation/\\1/)s", MySpace::FooClass)

noting that the 2nd argument operates on the target language proxy name
(not the C++ symbol name).

The branch also has Vladimir's override/virtual fix for interfaces, but has
regressed the extend testcases. When this is fixed, I'd like to merge all
of it to master unless there are any other comments.

William
Paul Donohue
2016-03-05 15:07:54 UTC
Permalink
Sorry, I keep getting pulled off of this to work on other things. I do believe I have some additional use cases and improvements to contribute, so I will try to prioritize this during the coming week.
Post by William S Fulton
Post by Vladimir Kalinin
I agree that there is a lot of stuff hardcoded, that should normally
Post by Vladimir Kalinin
be customizable, but w/o much real world use cases it is hard to tell
what exactly should be customized and how.
I can sort this out if the general code generation approach is
satisfactory. Am waiting for Paul's feedback on the current state
first.
Paul, any input?
Post by Vladimir Kalinin
I've merged with the latest in master so now the 'interfaces' branch
is up to date with master.
I've pushed my latest changes to the interfaces branch. There are a few
- merged in code from master to the branch
- moved code into typemaps and expanded types supported
- various corner cases fixed and added plenty of testcases
- re-organised the implementation
- added error checking
- added in Java premature garbage collection prevention parameter support
for these interfaces
- support nspace feature and namespaces in general
- renamed original macros and removed the need for providing an interface
%interface(TYPE) - leaves proxy class name unchanged and names the
interface with a I prefix
%interface_impl(TYPE) - renames proxy class with SwigImpl suffix and the
interface name is what the proxy class would have been called
%interface_custom(IMPL, INTERFACE, TYPE) - for providing custom proxy and
%interface_custom("FooImplementation", "IFoo", MySpace::FooClass)
namespace MySpace {
struct FooClass { ... };
struct DerivedClass : FooClass { ... };
}
results in a Java proxy class called FooImplementation and Java interface
called IFoo. A generic version of this renaming can be obtained with the
%interface_custom("%(rstrip:[Class])sImplementation",
"I%(regex:/(.*)Implementation/\\1/)s", MySpace::FooClass)
noting that the 2nd argument operates on the target language proxy name
(not the C++ symbol name).
The branch also has Vladimir's override/virtual fix for interfaces, but has
regressed the extend testcases. When this is fixed, I'd like to merge all
of it to master unless there are any other comments.
William
------------------------------------------------------------------------------
Vladimir Kalinin
2016-03-05 16:37:51 UTC
Permalink
------------------------------------------------------------------------------
William S Fulton
2016-03-11 20:06:39 UTC
Permalink
Thanks Vladimir, that has helped. Yes, I think the override fix should be
done in allocate.cxx. I think D would make good use of it too.

I've now added some documentation to Java.html and merged it into master.
I'd urge anyone interested in this new feature to test it and provide
comments and patches to fix any problems asap before we think of releasing
3.0.9.

William
Post by Vladimir Kalinin
Hi William,
I fixed the "extend" case, but still it will not work if we override some
"interface" function in the extension class.
I believe my whole attempt to fix that at the module level has failed, and
the check should be moved up to the
allocate.cxx, function_is_defined_in_bases(). Not that it is really urgent
though.
Best regards,
-----Original Message-----
On 12 February 2016 at 08:03, William S Fulton <
On 10 February 2016 at 23:34, Vladimir Kalinin <
Post by Vladimir Kalinin
I agree that there is a lot of stuff hardcoded, that should normally
be customizable, but w/o much real world use cases it is hard to tell
what exactly should be customized and how.
I can sort this out if the general code generation approach is
satisfactory. Am waiting for Paul's feedback on the current state
first.
Paul, any input?
I've merged with the latest in master so now the 'interfaces' branch
is up to date with master.
I've pushed my latest changes to the interfaces branch. There are a few
- merged in code from master to the branch
- moved code into typemaps and expanded types supported
- various corner cases fixed and added plenty of testcases
- re-organised the implementation
- added error checking
- added in Java premature garbage collection prevention parameter support
for these interfaces
- support nspace feature and namespaces in general
- renamed original macros and removed the need for providing an interface
%interface(TYPE) - leaves proxy class name unchanged and names the
interface with a I prefix
%interface_impl(TYPE) - renames proxy class with SwigImpl suffix and the
interface name is what the proxy class would have been called
%interface_custom(IMPL, INTERFACE, TYPE) - for providing custom proxy
%interface_custom("FooImplementation", "IFoo", MySpace::FooClass)
namespace MySpace {
struct FooClass { ... };
struct DerivedClass : FooClass { ... };
}
results in a Java proxy class called FooImplementation and Java interface
called IFoo. A generic version of this renaming can be obtained with the
%interface_custom("%(rstrip:[Class])sImplementation",
"I%(regex:/(.*)Implementation/\\1/)s", MySpace::FooClass)
noting that the 2nd argument operates on the target language proxy name
(not the C++ symbol name).
The branch also has Vladimir's override/virtual fix for interfaces, but
has regressed the extend testcases. When this is fixed, I'd like to merge
all of it to master unless there are any other comments.
William
Vladimir Kalinin
2013-06-18 10:27:01 UTC
Permalink
I also added the abstract classes support (the second type) to my
development branch I mentioned earlier. Feel free to check it out.
Syntax looks like
%feature("abstract", impname = "IMPL") CTYPE;
plus some typemaps (all packed in macro DECLARE_ABSTRACT).

-----Original Message-----
My project has two types of classes that contain pure virtual methods.
The first is similar to your case, where the class only contains pure
virtual methods. In this case, the desired result it to have swig
generate a C# or Java interface. The second case is classes that contain
a mixture of pure virtual methods and non-virtual methods. For this
second case, the desired result is for swig to generate an abstract C#
or Java class where the pure virtual methods are abstract.

Currently, swig generates a C# and Java class with non-abstract methods
for the pure virtual methods. This creates confusion to developers
implementing the methods in the target language and causes runtime
errors when they fail to implement all of the methods.

Brant
Post by Vladimir Kalinin
Hi Brant,
No, I didn't work on this project recently. You see - for my
applications it is enough to convert to interfaces C++ classes
containing only pure virtual functions and no data members.
Converting to interfaces the classes with data members and non-pure virtual
member functions is a lot more complicated, especially when/if virtual
inheritance is used. I definitely intend to finish this work (if no
one else will volunteer to do it), but I can't make any promises about
timing.
BTW, what do you think about the questions discussed in the previous
mail?
Best regards,
----- Original Message -----
I am interested in using this feature in my project. Has there been any
movement in getting this merged into swig?
Once this is working in the C# module, I would also be interested in
porting it over to the Java module.
Brant
Post by Vladimir Kalinin
Hi William,
Thanks for the test, I quite forgot about it. It revealed a case
%feature ("interface") Base2;
struct Base1 { virtual void f1(){}};
struct Base2 { virtual void f2(){}};
struct Descendant : Base1, Base2 {};
Note that Base2::f2() function is not abstract, and when Base2 is
converted to interface, Base2::f2() implementation should be injected
to the "Descendant" proxy class (probably using "extend").
(I didn't consider this case because in our project abstract base
classes are very like C#/Java interfaces and never contain
implementations, but anyway, this case is quite feasible.)
What do you think about "extend"? I can't really say when it
should be injected. The simplest place is the parser, but I didn't want to
touch the parser with these language specific changes.
The only other solution I can think
about is copying function's parse tree nodes from the "interfaces" to
the descendant classes, marking them with some runtime attribute, so
that proper "upcast" pointer would be used for them instead of
swigPtr. This can be done in the language module at the start of the
class handler.
Any other suggestions?
BTW, I didn't find any traces of the solution of that problem in ZhiYang's
code.
-----Original Message-----
Hi Vladimir
Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?
BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.
William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2242 / Virus Database: 3162/5832 - Release Date: 05/17/13
Vladimir Kalinin
2013-05-29 20:37:59 UTC
Permalink
I finished implementation of "feature:interface" (to some extent), for
both C# and Java. The test case you mentioned is added and passing.

There is a known deficiency in the implementation - if for some reason
direct call of the "interface" function is impossible in C++ (e.g. it
was marked as private in the intermediate base class, or there is a
complex multiple inheritance structure), C wrapper will be generated
incorrect (without proper upcast chain). I didn't find a way to
generate a proper upcast in the language module - all the related
functionality seem to be encapsulated in Swig/cwrap.c, and I want to
avoid touching it. Other way to generate the upcasts is to attach a
"feature:action" to each implementation method, but I don't like this
idea either.

An illustration to the above:

struct Base{ virtual void foo() = 0; }
class D1 : public Base {
private:
virtual void foo(){}
}
class D2 : public D1 {
}

let's declare Base an interface, then D2 proxy class will implement
Base interface and will have public foo() proxy method.
In C wrappers we will have something like:

SWIGEXPORT void JNICALL Java_com_blablaJNI_D2_1foo(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
<skip>
arg1 = (D2*)jarg1;
<skip>
result = (arg1)->foo();
<skip>

Which won't compile because D2::foo is resolved to D1::foo and is
private. In this case simple upcast would fix the code:
result = ((Base*)arg1)->foo();

But in more complicated cases, like

struct Base{ virtual int foo() = 0; int data;}
struct D1 : Base {
virtual int foo(){return data;}
}
struct D2 : Base {
virtual int foo(){return data;}
}
struct C : D1, D2 {}

There probably should be a way for a user to select the proper upcast
chain, because either in C# or in Java there can't be 2 different 'foo'
methods implementing the same interface Base.foo

Anyway, this is just a hypothetical situation, hope no one will ever
encounter it.

-----Original Message-----
Hi Vladimir

Great news, although I'm finding it hard to understand what is
implemented without applying the patch. I'd like to see proper
interfaces, that is simple ABCs, working first and possibly you haven't
addressed this yet? The test in
http://thread.gmane.org/gmane.comp.programming.swig.devel/18403 is what
I originally asked Zhiyang to focus on first. I would like to see this
test added to your github fork and can you write the C# equivalent to
the Java runtime test so I can more easily see what state it is in?

BTW, I havn't forgotten about your wonderful nested class work, I just
need to find some more time to take a good look and will do so once
2.0.10 is out the door.

William
Post by Vladimir Kalinin
I finally found some time to implement this feature (only for C# for now)
You may look at it here: https://github.com/wkalinin/swig/tree/interfaces
It works as a combination of a feature and a set of typemaps.
Here are 2 versions of the typemaps, w/o namespaces and with them
%define DECLARE_INTERFACE(CTYPE, INTERFACE, IMPL)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(INTERFACE)new IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
IMPL ret = new IMPL($imcall,true);
$excode
return (INTERFACE)ret;
}
%enddef
%define DECLARE_INTERFACE_NS(CTYPE, INTERFACE, IMPL, NAMESPACE)
%rename (IMPL) CTYPE;
%feature("interface", name = "INTERFACE", cptr = "GetCPtr") CTYPE;
%typemap(cstype) CTYPE*, const CTYPE& "NAMESPACE.INTERFACE"
%typemap(csdirectorout) CTYPE*, const CTYPE& "$cscall.GetCPtr()"
%typemap(csdirectorin) CTYPE*, const CTYPE&
%{
(NAMESPACE.INTERFACE)new NAMESPACE.IMPL($iminput,false)
%}
%typemap(csin) CTYPE*, const CTYPE& "$csinput.GetCPtr()"
%typemap(csout, excode=SWIGEXCODE) CTYPE*, const CTYPE&
{
NAMESPACE.IMPL ret = new NAMESPACE.IMPL($imcall,true);
$excode
return (NAMESPACE.INTERFACE)ret;
}
%enddef
%rename is optionally used if implementation class should be named
differently from the original class.
These macros are more of a sample/illustration, because e.g. in our
project we use quite different typemaps to implement proper
downcast behaviour.
I attached the sample file I used for testing.
-----Original Message-----
interface IA { IntPtr getCPtr(); }
interface IB : IA { IntPtr getCPtr(); }
interface IC { IntPtr getCPtr(); }
class Foo : IA, IB, IC {
...
IntPtr IA.getCPtr() { return ???; }
IntPtr IB.getCPtr() { return ???; }
IntPtr IC.getCPtr() { return ???; }
}
Foo foo = ...;
IntPtr aPtr = ((IA)foo).getCPtr();
Explicit interface implementations have the advantage that they are less visible (interface methods are always public, technically, but they are invisible on an object of type "Foo" until you cast to IA or IB or IC.)
Note that since these methods are public, there is greater reason to make it possible to rename them (it is very annoying that opaque pointers are hardcoded with the name SWIGTYPE_p_Xyz, so I %ignore everything that would cause an opaque pointer to be produced, or map opaque pointers to IntPtr instead, through typemaps.)
Date: 03/22/2013 01:25 PM
Subject: Re: [Swig-devel] Abstract base classes to interfaces conversion
Thinking some more about the subject, it turns out that the only reliable way to obtain valid C pointer from the interface is to extend the interface with the corresponding function (like "internal IntPtr getCPtr();" ).
It cannot be called just getCPtr(), because if some class implements several interfaces, it has to implement several "getCPtr" functions. Interface name may be appended|prepended to the function name to distinguish them.
Implementation of these functions is the same as that of SwigUPCAST()
-----Original Message-----
struct A { int a; void fa(); }
struct B { int b; void fb(); }
struct C : A, B { int c; void fc(); }
public interface IB {
int b { get; set; }
void fb();
}
public class B : IB {
public B(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
...
}
public class C : A, IB {
public C(...) {...}
public int b { get { ... } set { ... } }
public void fb() { ... }
public int c { get { ... } set { ... } }
public void fc() { ... }
...
}
This way, it is possible to create a standalone B that is not a C. Of course, if B is an abstract base class then an interface alone should suffice, i.e. only an interface IB is needed, not a class B.
// C can convert to B implicitly
public static implicit operator B(C c) { ??? }
But this feature is optional, since the user could add the necessary code manually, or (I assume) with help from a macro.
Date: 03/19/2013 04:55 PM
Subject: [Swig-devel] Abstract base classes to interfaces conversion
As far as I know, currently there is no easy way to convert C++ abstract base
classes to Java/C# interfaces. (short of redeclaring the classes and
doing some more work)
I found the only reference to the attempt to implement that feature
here: http://thread.gmane.org/gmane.comp.programming.swig.devel/18403
Is there any information about the status of that work?
(As I understand, the patch posted in that thread is far from
perfection)
Maybe there is some alternative solution being worked at in some SWIG branch?
If no one is planning to implement that feature in near future, I
will do it (in some way at least).
(Because, converting abstract base classes to interfaces is
currently the most time consuming feature in our
project wrappers (after nested classes were implemented)).
I think "feature:interface" syntax proposed by Zhiyang Jiang is ok.
Any suggestions, advices?
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
Swig-devel mailing list
https://lists.sourceforge.net/lists/listinfo/swig-devel
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2241 / Virus Database: 3162/5756 - Release Date: 04/19/13
Continue reading on narkive:
Loading...