From: William S F. <ws...@fu...> - 2013-07-12 21:42:57
|
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 On 08/07/13 14:41, Vladimir Kalinin wrote: > 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 > > On 18/06/13 20:57, Vladimir Kalinin wrote: >> 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:vka...@op... >> >> ----- 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 >> >> On 29/05/13 15:18, Vladimir Kalinin wrote: >>> 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 >>> >>> On 5/16/13 10:39 AM, Vladimir Kalinin wrote: >>>> 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:vka...@op... >>>> >>>> ----- 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 >>>> >>>> On 4/21/13 1:14 PM, Vladimir Kalinin wrote: >>>>> 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 >>>>> >>>>> On 16/04/13 21:10, Vladimir Kalinin wrote: >>>>>> 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 <vka...@op...> >>>>>> To: David Piepgrass <Dav...@tr...> >>>>>> Cc: <swi...@li...> >>>>>> 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 <vka...@op...> >>>>>> To: <swi...@li...> >>>>>> 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 >>>>>> Swi...@li... >>>>>> 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 >>>>> Swi...@li... >>>>> 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 >>>> Swi...@li... >>>> 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 >>> Swi...@li... >>> https://lists.sourceforge.net/lists/listinfo/swig-devel >>> >> >> . >> > > |