zhiyang jiang | 10 Aug 10:31

Re: Better improvement for the multi inheritance



2008/7/30 William S Fulton <wsf <at> fultondesigns.co.uk>
zhiyang jiang wrote:


2008/7/14 William S Fulton <wsf <at> fultondesigns.co.uk <mailto:wsf <at> fultondesigns.co.uk>>:


   zhiyang jiang wrote:


       Hi William
       Through a few days' work, i make some changes in SWIG source for
       bettering the multi inheritance .Now  the multi inheritance
       likes this:


   Hi,

   Hope you are well. Thanks for this. I'm a bit overloaded at the
   moment, but will have a look in the next few days.

   William


this is a new patch!

--
I am sorry for taking so long to look at this, there is too much going on at the moment.

I think you have left out the .i test and runtime test for multiple_inheritance_abstract in your second patch, so I looked for these in your first patch... not a problem unless you changed them.

Having looked at the patch, the following change is a big concern:

-    super($imclassname.SWIG$javaclassnameUpcast(cPtr), cMemoryOwn);
+    //super($imclassname.SWIG$javaclassnameUpcast(cPtr), cMemoryOwn);

This upcast is absolutely necessary as the pointer to the base class might not be the same value as the pointer to a derived class, therefore the original pointer must be stored in the derived class as well as the pointer value up cast to the base class.
The  SWIG$javaclassnameUpcast(cPtr) just return the pointer of derived classes' first base class,so i don't think it is useful when up cast to the case class.But it will get undefined behavior when calling a c++ function  that it has a Base classes as parameter ,see testcase's function foo6(),foo7(),foo8() in java.  i  think it may be caused by the conversion of pointer from java to c++,when the address of a class  is converted from java to c++,some type info will lost,i am not sure about it.

The following also won't work when a null pointer is being used:

-%typemap(javain) SWIGTYPE *& "$*javaclassname.getCPtr($javainput)"
+/*%typemap(javain) SWIGTYPE *& "$*javaclassname.getCPtr($javainput)"*/
+%typemap(javain) SWIGTYPE *& "$javainput.getCPtr()"
The new patch will check the $javainput use a condition  expression now!

I suggest you add another test method to your testcase, one which takes ABase1* as a parameter. Also CBase1*, CBase2* as both return types and input parameters.
I add some new functions into testcase, they test the base classes as parameters, but unfortunately, it will get unexpected results when use these functions, 

For any future patches, can I suggest you post them publicly. One of the lessons to be learnt in open source programming, which is encouraged for all Google summer of code students, is to develop in the open.

William

This patch works well when there is no c++ function that has a base class as its parameter,or it will get unexpected results ,and it will be ok when there are functions that has base class parameters in java, see the testcase about that.I am now finding what's wrong with it.


--
Best Regards
Jiang

Index: /home/jazy/workspace/SWIG/Examples/test-suite/common.mk
===================================================================
--- /home/jazy/workspace/SWIG/Examples/test-suite/common.mk	(revision 10659)
+++ /home/jazy/workspace/SWIG/Examples/test-suite/common.mk	(working copy)
@@ -221,6 +221,7 @@
 	minherit2 \
 	mixed_types \
 	multiple_inheritance \
+       multiple_inheritance_abstract \
 	name_cxx \
 	name_warnings \
 	namespace_class \
Index: /home/jazy/workspace/SWIG/Examples/test-suite/java/multiple_inheritance_abstract_runme.java
===================================================================
---
/home/jazy/workspace/SWIG/Examples/test-suite/java/multiple_inheritance_abstract_runme.java	(revision 0)
+++
/home/jazy/workspace/SWIG/Examples/test-suite/java/multiple_inheritance_abstract_runme.java	(revision 0)
@@ -0,0 +1,109 @@
+import multiple_inheritance_abstract.*;
+
+public class multiple_inheritance_abstract_runme {
+
+  static {
+    try {
+      System.loadLibrary("multiple_inheritance_abstract");
+    } catch (UnsatisfiedLinkError e) {
+      System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in
the SWIG Java documentation for help.\n" + e);
+      System.exit(1);
+    }
+  }
+//Test base class as a parameter in java
+int jfoo1(CBase1 cb1){
+return cb1.foo1();
+}
+int jbar1(ABase1 ab1){
+return ab1.bar1();
+}
+int jfoo2(CBase2 cb2){
+return cb2.foo2();
+}
+  public static void main(String argv[]) {
+ //Test Derived1
+   Derived1 d1=new Derived1();
+   if(d1.foo1()!=3)
+     throw new RuntimeException("Derived1::foo1() failed in multiple_inheritance_abstract");
+   if(d1.foo2()!=4)
+       throw new RuntimeException("Derived::foo2() failed in multiple_inheritance_abstract");
+//Test Derived2
+   Derived2 d2=new Derived2();
+   if(d2.foo1()!=6)
+       throw new RuntimeException("Derived2::foo1() failed in multiple_inheritance_abstract");
+   if(d2.bar1()!=5)
+       throw new RuntimeException("Derived2::bar1() failed in multiple_inheritance_abstract");
+//Test Derived3
+   Derived3 d3=new Derived3();
+   if( d3.foo1()!=7)
+       throw new RuntimeException("Derived3::foo1() failed in multiple_inheritance_abstract");
+   if(d3.foo2()!=8)
+       throw new RuntimeException("Derived3::foo2() failed in multiple_inheritance_abstract");
+   if(d3.bar1()!=9)
+       throw new RuntimeException("Derived3::bar1() failed in multiple_inheritance_abstract");
+//Test interfaces from c++ classes 
+   CBase1 cb1=new SWIGTYPE_CBase1();
+   CBase2 cb2=new SWIGTYPE_CBase2();
+   if(cb1.foo1()!=1)
+      throw new RuntimeException("CBase1::foo1() failed in multiple_inheritance_abstract");
+   if(cb2.foo2()!=2)
+      throw new RuntimeException("CBase2::foo2() failed in multiple_inheritance_abstract");
+   //Test abstract class as return value
+   ABase1 ab1=d3.clone();
+   if( ab1.bar1()!=9)
+       throw new RuntimeException("Derived3::bar1() through ABase1 failed in multiple_inheritance_abstract");
+//Test concrete base class as return value
+  CBase1 cb6=d2.clone();
+  CBase2 cb7=d1.clone();
+if(cb6.foo1()!=6)
+      throw new RuntimeException("Derived2::foo1() through CBase1 failed in multiple_inheritance_abstract");
+if(cb7.foo2()!=4)
+         throw new RuntimeException("Derived1:foo2() through ABase1 failed in multiple_inheritance_abstract");
+   //Test multi inheritance 
+   CBase1 cb3=new Derived1();
+   CBase1 cb4=new Derived3();
+   CBase2 cb5=new Derived3();
+   ABase1 ab6=new Derived2();
+   if(cb3.foo1()!=3)
+      throw new RuntimeException("Derived1::foo1()through CBase1 failed in multiple_inheritance_abstract");
+   if(cb4.foo1()!=7)
+      throw new RuntimeException("Derived3::foo1()through CBase1 failed in multiple_inheritance_abstract");
+   if(cb5.foo2()!=8)
+      throw new RuntimeException("Derived3::foo2()through CBase2 failed in multiple_inheritance_abstract");
+   if(ab6.bar1()!=5)
+      throw new RuntimeException("Derived2::bar1()through ABase1 failed in
multiple_inheritance_abstract");  
+//Test base classes as parameter in java 
+multiple_inheritance_abstract_runme mhar=new multiple_inheritance_abstract_runme();
+if(mhar.jfoo1(d1)!=3)
+   throw new RuntimeException("jfoo1()through Derived1 as parameter failed in multiple_inheritance_abstract");
+if(mhar.jfoo1(d2)!=6)
+   throw new RuntimeException("jfoo1()through Derived2 as parameter failed in multiple_inheritance_abstract");
+if(mhar.jfoo1(d3)!=7)
+   throw new RuntimeException("jfoo1()through Derived3 as parameter failed in multiple_inheritance_abstract");
+if(mhar.jfoo2(d1)!=4)
+   throw new RuntimeException("jfoo2()through Derived1 as parameter failed in multiple_inheritance_abstract");
+if(mhar.jfoo2(d3)!=8)
+   throw new RuntimeException("jfoo2()through Derived3 as parameter failed in multiple_inheritance_abstract");
+if(mhar.jbar1(d2)!=5)
+   throw new RuntimeException("jbar1()through Derived2 as parameter failed in multiple_inheritance_abstract");
+if(mhar.jbar1(d3)!=9)
+   throw new RuntimeException("jbar1()through Derived3 as parameter failed in multiple_inheritance_abstract");
+/*//Test ABase1 as a parameter
+ if(multiple_inheritance_abstract.foo6(d2)!=5)
+       throw new RuntimeException("foo6() through Derived2 as a parameter failed in multiple_inheritance_abstract");
+if(multiple_inheritance_abstract.foo6(d3)!=9)
+       throw new RuntimeException("foo6() through Derived3 as a parameter failed in multiple_inheritance_abstract");
+//Test CBase1 CBase2 as parameters
+if(multiple_inheritance_abstract.foo7(d3)!=7)
+       throw new RuntimeException("foo7() ,Derived3 as  a parameter failed in multiple_inheritance_abstract");
+if(multiple_inheritance_abstract.foo7(d1)!=3)
+       throw new RuntimeException("foo7() ,Derived1 as  a parameter failed in multiple_inheritance_abstract");
+if(multiple_inheritance_abstract.foo7(d2)!=6)
+       throw new RuntimeException("foo7() ,Derived3 as  a parameter failed in multiple_inheritance_abstract");
+if(multiple_inheritance_abstract.foo8(d3)!=4)
+       throw new RuntimeException("foo8() ,Derived3 as  a parameter failed in multiple_inheritance_abstract");
+if(multiple_inheritance_abstract.foo8(d1)!=8)
+       throw new RuntimeException("foo8() ,Derived1 as  a parameter failed in multiple_inheritance_abstract");*/
+   
+}
+}
Index: /home/jazy/workspace/SWIG/Examples/test-suite/multiple_inheritance_abstract.i
===================================================================
--- /home/jazy/workspace/SWIG/Examples/test-suite/multiple_inheritance_abstract.i	(revision 0)
+++ /home/jazy/workspace/SWIG/Examples/test-suite/multiple_inheritance_abstract.i	(revision 0)
@@ -0,0 +1,105 @@
+%module  multiple_inheritance_abstract
+
+%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE,
+	    SWIGWARN_CSHARP_MULTIPLE_INHERITANCE,
+	    SWIGWARN_PHP4_MULTIPLE_INHERITANCE) Derived1;	/* C#, Java, Php4 multiple inheritance */
+
+%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE,
+	    SWIGWARN_CSHARP_MULTIPLE_INHERITANCE,
+	    SWIGWARN_PHP4_MULTIPLE_INHERITANCE) Derived2;	/* C#, Java, Php4 multiple inheritance */
+%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE,
+	    SWIGWARN_CSHARP_MULTIPLE_INHERITANCE,
+	    SWIGWARN_PHP4_MULTIPLE_INHERITANCE) Derived3;	/* C#, Java, Php4 multiple inheritance */
+%feature("interface") ABase1;
+%feature("interface") CBase1;
+%feature("interface") CBase2;
+
+
+%inline %{
+struct CBase1 {
+virtual void foo9(){
+return ;
+} 
+virtual int foo1(){
+ return 1;
+}
+int foo3(){
+return 10;
+}
+virtual ~CBase1(){
+}
+};
+struct CBase2{
+virtual int foo2(){
+return 2;
+}
+virtual ~CBase2(){
+}
+};
+struct ABase1{
+virtual int  bar1()=0;
+virtual ~ABase1(){
+}
+};
+
+struct Derived1 : CBase2,CBase1{
+  virtual int foo1(){
+return 3;
+}
+virtual void foo9(){
+return;
+}
+virtual int foo2(){
+return 4;
+}
+virtual CBase2* clone(){
+return new Derived1(*this);
+}
+};
+struct Derived2:CBase1,ABase1{
+virtual int bar1(){
+return 5;
+}
+virtual int foo1(){
+return 6;
+}
+virtual void foo9(){
+return;
+}
+virtual CBase1* clone(){
+return new Derived2(*this);
+}
+};
+struct Derived3:ABase1,CBase1,CBase2{
+virtual int foo1(){
+return 7;
+}
+virtual int foo2(){
+return 8;
+}
+virtual int bar1(){
+return 9;
+}
+virtual void foo9(){
+}
+virtual ABase1* clone(){
+return new Derived3(*this);
+}
+};
+ABase1* foo4(Derived3 d){
+return d.clone();
+}
+int foo5(CBase1 cb1,CBase2 cb2){
+return cb1.foo1()+cb2.foo2();
+}
+int foo6(ABase1* pab1){
+return  pab1->bar1();
+}
+int foo7(CBase1* pcb1){
+return pcb1->foo1();
+}
+int foo8(CBase2* pcb2){
+return pcb2->foo2();
+}
+
+%}

Property changes on: /home/jazy/workspace/SWIG/Examples/test-suite/multiple_inheritance_abstract.i
___________________________________________________________________
Name: svn:executable
   + *

Index: /home/jazy/workspace/SWIG/Lib/java/java.swg
===================================================================
--- /home/jazy/workspace/SWIG/Lib/java/java.swg	(revision 10659)
+++ /home/jazy/workspace/SWIG/Lib/java/java.swg	(working copy)
@@ -967,9 +967,10 @@
                  jdoubleArray,
                  jobjectArray
     "$javainput"
-%typemap(javain) SWIGTYPE "$&javaclassname.getCPtr($javainput)"
-%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "$javaclassname.getCPtr($javainput)"
-
+/*%typemap(javain) SWIGTYPE "$&javaclassname.getCPtr($javainput)"
+%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "$javaclassname.getCPtr($javainput)"*/
+%typemap(javain) SWIGTYPE "(($javainput!=null)?$javainput.getCPtr():0)"
+%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "(($javainput!=null)?$javainput.getCPtr():0)"
 /* The javaout typemap is used for converting function return types from the return type
  * used in the JNI class to the type returned by the proxy, module or type wrapper class. */
 %typemap(javaout) bool,               const bool &,
@@ -1030,7 +1031,8 @@
 %typemap(jni) SWIGTYPE *& "jlong"
 %typemap(jtype) SWIGTYPE *& "long"
 %typemap(jstype) SWIGTYPE *& "$*javaclassname"
-%typemap(javain) SWIGTYPE *& "$*javaclassname.getCPtr($javainput)"
+/*%typemap(javain) SWIGTYPE *& "$*javaclassname.getCPtr($javainput)"*/
+%typemap(javain) SWIGTYPE *& "(($javainput!=null)?$javainput.getCPtr():0)"
 %typemap(javaout) SWIGTYPE *& {
     long cPtr = $jnicall;
     return (cPtr == 0) ? null : new $*javaclassname(cPtr, $owner);
@@ -1064,8 +1066,11 @@
     swigCPtr = cPtr;
   }

-  CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+/*  CPTR_VISIBILITY  long getCPtr($javaclassname obj) {
     return (obj == null) ? 0 : obj.swigCPtr;
+  }*/
+  public  long getCPtr() {
+    return swigCPtr;
   }
 %}

@@ -1072,15 +1077,23 @@
 // Derived proxy classes
 %typemap(javabody_derived) TYPENAME %{
   private long swigCPtr;
-
+  protected boolean swigCMemOwn;
+  //private long swigPPtr;
   PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
-    super($imclassname.SWIG$javaclassnameUpcast(cPtr), cMemoryOwn);
+    //super($imclassname.SWIG$javaclassnameUpcast(cPtr), cMemoryOwn);
+    //swigPPtr=$imclassname.SWIG$javaclassnameUpcast(cPtr);
     swigCPtr = cPtr;
   }

-  CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+  /*CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
     return (obj == null) ? 0 : obj.swigCPtr;
+  }*/
+  public  long getCPtr() {
+    return swigCPtr;
   }
+ /* public long getPPtr(){
+  return swigPPtr;
+  }*/
 %}
 %enddef

@@ -1101,8 +1114,11 @@
     swigCPtr = 0;
   }

-  protected static long getCPtr($javaclassname obj) {
+ /* protected static long getCPtr($javaclassname obj) {
     return (obj == null) ? 0 : obj.swigCPtr;
+  }*/
+  public  long getCPtr() {
+    return swigCPtr;
   }
 %}

@@ -1160,7 +1176,8 @@
       $jnicall;
     }
     swigCPtr = 0;
-    super.delete();
+    //super.delete();
+   // swigPPtr=0;
   }

 %typemap(directordisconnect, methodname="swigDirectorDisconnect") SWIGTYPE %{
Index: /home/jazy/workspace/SWIG/Source/CParse/parser.y
===================================================================
--- /home/jazy/workspace/SWIG/Source/CParse/parser.y	(revision 10659)
+++ /home/jazy/workspace/SWIG/Source/CParse/parser.y	(working copy)
@@ -3189,8 +3189,8 @@
 		       nscope_inner = 0;
 		     }
 		   }
-		   Setattr($$,"name",$3);
-
+		   Setattr($$,"name",$3);	  
+            /*Printf(stdout,"the cpares features are %s\n.",Getattr(Swig_cparse_features(),"feature:interface"));*/
 		   Delete(class_rename);
                    class_rename = make_name($$,$3,0);
 		   Classprefix = NewString($3);
@@ -3223,6 +3223,13 @@
 		   if (bases) {
 		     Iterator s;
 		     for (s = First(bases); s.item; s = Next(s)) {
+		     /*set the Derived class has a interface base feature*/
+	         if(GetFlag(s.item,"feature:interface")){
+	             String* interface=NewStringf("feature:interface:%s",Getattr(s.item,"name"));
+		         SetFlag($$,interface);
+		         Delete(interface);
+	         }
+	         
 		       Symtab *st = Getattr(s.item,"symtab");
 		       if (st) {
 			 Setfile(st,Getfile(s.item));
Index: /home/jazy/workspace/SWIG/Source/Modules/java.cxx
===================================================================
--- /home/jazy/workspace/SWIG/Source/Modules/java.cxx	(revision 10659)
+++ /home/jazy/workspace/SWIG/Source/Modules/java.cxx	(working copy)
@@ -32,7 +32,8 @@
   File *f_directors;
   File *f_directors_h;
   List *filenames_list;
-
+  List *interfaces_list; //list to save interfaces
+  
   bool proxy_flag;		// Flag for generating proxy classes
   bool nopgcpp_flag;		// Flag for suppressing the premature garbage collection prevention parameter
   bool native_function_flag;	// Flag for when wrapping a native function
@@ -70,7 +71,7 @@
   String *imclass_cppcasts_code;	//C++ casts up inheritance hierarchies intermediary class code
   String *imclass_directors;	// Intermediate class director code
   String *destructor_call;	//C++ destructor call if any
-
+  String *interface_code;  // C++ base class from %feature("interface")
   // Director method stuff:
   List *dmethods_seq;
   Hash *dmethods_table;
@@ -106,6 +107,7 @@
       f_directors(NULL),
       f_directors_h(NULL),
       filenames_list(NULL),
+      interfaces_list(NULL),
       proxy_flag(true),
       nopgcpp_flag(false),
       native_function_flag(false),
@@ -141,6 +143,7 @@
       imclass_cppcasts_code(NULL),
       imclass_directors(NULL),
       destructor_call(NULL),
+      interface_code(NULL),
       dmethods_seq(NULL),
       dmethods_table(NULL),
       n_dmethods(0),
@@ -167,7 +170,18 @@
     }
     return NULL;
   }
-
+   /*isInterface()
+    * Test wheather "name" is a interface in "l"
+    */
+bool isInterface(List* l,String* name){
+	Iterator i;
+	for(i=First(l);i.item;i=Next(i)){
+		if(Cmp(name,i.item)==0){		
+			return true;
+		}
+	}
+	return false;
+}
   /* -----------------------------------------------------------------------------
    * makeValidJniName()
    * ----------------------------------------------------------------------------- */
@@ -195,7 +209,7 @@

     return dirclassname;
   }
-
+  
   /* ------------------------------------------------------------
    * main()
    * ------------------------------------------------------------ */
@@ -327,7 +341,7 @@

     swig_types_hash = NewHash();
     filenames_list = NewList();
-
+    interfaces_list=NewList();
     // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
     if (!imclass_name) {
       imclass_name = NewStringf("%sJNI", Getattr(n, "name"));
@@ -343,6 +357,7 @@
     imclass_class_code = NewString("");
     proxy_class_def = NewString("");
     proxy_class_code = NewString("");
+    interface_code=NewString("");
     module_class_constants_code = NewString("");
     imclass_baseclass = NewString("");
     imclass_interfaces = NewString("");
@@ -596,6 +611,8 @@
     proxy_class_def = NULL;
     Delete(proxy_class_code);
     proxy_class_code = NULL;
+    Delete(interface_code);
+    interface_code=NULL;
     Delete(module_class_constants_code);
     module_class_constants_code = NULL;
     Delete(imclass_baseclass);
@@ -1552,14 +1569,18 @@
     String *baseclass = NULL;
     String *c_baseclassname = NULL;
     String *typemap_lookup_type = Getattr(n, "classtypeobj");
+    String *interface=NewStringf("");
     bool feature_director = Swig_directorclass(n) ? true : false;
-
+    bool isExtend=true; //wheather the keyword extend is needed
     // Inheritance from pure Java classes
     Node *attributes = NewHash();
-    const String *pure_baseclass = typemapLookup("javabase", typemap_lookup_type, WARN_NONE, attributes);
+   const String *pure_baseclass = typemapLookup("javabase", typemap_lookup_type, WARN_NONE, attributes);
     bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false;
     Delete(attributes);
-
+    //the interface itself is the base of the classes like SWIGTYEP_XXX 
+    if(GetFlag(n,"feature:interface")){
+    	Printf(interface,"%s",Getattr(n,"name"));
+    }
     // C++ inheritance
     if (!purebase_replace) {
       List *baselist = Getattr(n, "bases");
@@ -1570,6 +1591,17 @@
         }
         if (base.item) {
           c_baseclassname = Getattr(base.item, "name");
+          
+          //we get the fist base class from here
+          String* aFeature=NewStringf("feature:interface:%s",c_baseclassname);
+          if(GetFlag(n,aFeature)){
+        	                 isExtend=false;
+                      	   Printf(interface,"%s",c_baseclassname);
+                      		if(Next(base).item&&!GetFlag(Next(base).item,"feature:ignore")){
+                      		            	Printf(interface,",");
+                      	}
+                      }
+          Delete(aFeature);
           baseclass = Copy(getProxyName(c_baseclassname));
           if (baseclass)
             c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
@@ -1576,10 +1608,20 @@
           base = Next(base);
           /* Warn about multiple inheritance for additional base class(es) */
           while (base.item) {
+        	  //add other interfaces into string "interface"
+        	  aFeature=NewStringf("feature:interface:%s",Getattr(base.item, "name"));
             if (GetFlag(base.item, "feature:ignore")) {
               base = Next(base);
               continue;
+            }else{
+            	if(GetFlag(n,aFeature)){
+            		Printf(interface,"%s",Getattr(base.item, "name"));
+            		if(Next(base).item&&!GetFlag(Next(base).item,"feature:ignore")){
+            		            	Printf(interface,",");
+            	}
             }
+            }
+            Delete(aFeature);
             String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
             String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
             Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
@@ -1585,6 +1627,8 @@
             Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
                          "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n",
proxyclassname, baseclassname);
             base = Next(base);
+            
+            
           }
         }
       }
@@ -1591,8 +1635,11 @@
     }

     bool derived = baseclass && getProxyName(c_baseclassname);
+    if(!isExtend){
+        	 baseclass=NULL;
+    	  
+        }
     const String *wanted_base = baseclass ? baseclass : pure_baseclass;
-
     if (purebase_replace) {
       wanted_base = pure_baseclass;
       derived = false;
@@ -1610,8 +1657,9 @@
     Printv(proxy_class_def, typemapLookup("javaimports", typemap_lookup_type, WARN_NONE),	//
Import statements
 	   "\n", typemapLookup("javaclassmodifiers", typemap_lookup_type,
WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers
 	   " $javaclassname",	// Class name and bases
-	   (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(pure_interfaces) ?	// Pure Java interfaces
-	   " implements " : "", pure_interfaces, " {", derived ? typemapLookup("javabody_derived",
typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) :	// main body of class
+	   (*Char(wanted_base)) ? " extends " : "", wanted_base,
*Char(pure_interfaces)||(Cmp(interface,"")) ?	
+	   " implements " : "",interface,*Char(pure_interfaces)?",":"", pure_interfaces, // Pure Java interfaces
+	   " {", derived ? typemapLookup("javabody_derived", typemap_lookup_type,
WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) :	// main body of class
 	   typemapLookup("javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),	// main
body of class
 	   NIL);

@@ -1673,6 +1721,7 @@
       Delete(destruct_jnicall);
       Delete(release_jnicall);
       Delete(take_jnicall);
+      Delete(interface);
     }

     Delete(attributes);
@@ -1683,8 +1732,17 @@
 	   "\n", NIL);

     // Substitute various strings into the above template
-    Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
-    Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
+    if(GetFlag(n,"feature:interface")){
+    	String* mangleName=NewStringf("SWIGTYPE_%s",proxy_class_name);
+    	Replaceall(proxy_class_code, "$javaclassname", mangleName);
+    	Replaceall(proxy_class_def, "$javaclassname", mangleName);
+    	Delete(mangleName);
+    }else{
+    	Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
+    	Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
+    }
+    
+    

     Replaceall(proxy_class_def, "$module", module_class_name);
     Replaceall(proxy_class_code, "$module", module_class_name);
@@ -1740,8 +1798,15 @@
 	Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
 	SWIG_exit(EXIT_FAILURE);
       }
-
-      String *filen = NewStringf("%s%s.java", SWIG_output_directory(), proxy_class_name);
+      
+      String *filen=NULL;
+      //add the class name declared by %feauture("interface") into interfaces_list
+      if(GetFlag(n,"feature:interface")){
+    	  Append(interfaces_list,Getattr(n,"name"));
+    	  filen = NewStringf("SWIGTYPE_%s%s.java", SWIG_output_directory(), proxy_class_name);
+      }else{
+    	  filen = NewStringf("%s%s.java", SWIG_output_directory(), proxy_class_name);
+      }
       f_proxy = NewFile(filen, "w");
       if (!f_proxy) {
 	FileErrorDisplay(filen);
@@ -1759,7 +1824,7 @@

       Clear(proxy_class_def);
       Clear(proxy_class_code);
-
+      Clear(interface_code);
       destructor_call = NewString("");
       proxy_class_constants_code = NewString("");
     }
@@ -1812,7 +1877,22 @@
 	Wrapper_print(dcast_wrap, f_wrappers);
 	DelWrapper(dcast_wrap);
       }
-
+     //if the class is declared as interface in SWIG,generate a java interface
+      if(GetFlag(n,"feature:interface")){
+          	String *interfaceName=NewStringf("%s%s.java",SWIG_output_directory(),proxy_class_name);
+          	    File* f_interface= NewFile(interfaceName, "w");
+          	    emitBanner(f_interface);
+          	    if (Len(package) > 0)
+          	    	Printf(f_interface, "package %s;\n", package);
+          	    Printf(f_interface,"public interface %s%s",SWIG_output_directory(),proxy_class_name);
+          	    Printf(f_interface,"{\n");
+          	    Printv(f_interface,interface_code, NIL);
+          	    // add two common methods in java interface
+          	    Printf(f_interface,"long getCPtr();\n");
+          	    Printf(f_interface,"void delete();\n");
+          	    Printf(f_interface,"}");
+          	    Delete(interfaceName);
+          }
       emitDirectorExtraMethods(n);

       Delete(proxy_class_name);
@@ -1822,7 +1902,9 @@
       Delete(proxy_class_constants_code);
       proxy_class_constants_code = NULL;
     }
-
+   
+    
+    
     return SWIG_OK;
   }

@@ -1884,6 +1966,7 @@
   void proxyClassFunctionHandler(Node *n) {
     SwigType *t = Getattr(n, "type");
     ParmList *l = Getattr(n, "parms");
+    String*  storage=Getattr(n,"storage");
     String *intermediary_function_name = Getattr(n, "imfuncname");
     String *proxy_function_name = Getattr(n, "proxyfuncname");
     String *tm;
@@ -1895,7 +1978,9 @@
     bool setter_flag = false;
     String *pre_code = NewString("");
     String *post_code = NewString("");
-
+    
+    String *interfaceBody=NewString("");
+   
     if (!proxy_flag)
       return;

@@ -1924,7 +2009,8 @@
       // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be
the base of the C++ return type
       SwigType *covariant = Getattr(n, "covariant");
       substituteClassname(covariant ? covariant : t, tm);
-      Printf(return_type, "%s", tm);
+      
+        Printf(return_type, "%s", tm);
       if (covariant)
 	Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number,
 		     "Covariant return types not supported in Java. Proxy method will return %s.\n",
SwigType_str(covariant, 0));
@@ -1941,10 +2027,14 @@
     const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
     methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
     Printf(function_code, "  %s ", methodmods);
+   
     if (static_flag)
       Printf(function_code, "static ");
     Printf(function_code, "%s %s(", return_type, proxy_function_name);
-
+    // extract virtual function return type  for java interface
+    if(Cmp(storage,"virtual")==0){
+       Printf(interfaceBody, "%s %s(", return_type, proxy_function_name);
+    }
     Printv(imcall, imclass_name, ".$imfuncname(", NIL);
     if (!static_flag) {
       Printf(imcall, "swigCPtr");
@@ -1994,7 +2084,7 @@
 	/* Get the Java parameter type */
 	if ((tm = Getattr(p, "tmap:jstype"))) {
 	  substituteClassname(pt, tm);
-	  Printf(param_type, "%s", tm);
+	    Printf(param_type, "%s", tm);
 	} else {
 	  Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap
defined for %s\n", SwigType_str(pt, 0));
 	}
@@ -2031,10 +2121,17 @@
 	}

 	/* Add parameter to proxy function */
-	if (gencomma >= 2)
+	if (gencomma >= 2){
 	  Printf(function_code, ", ");
+	  if(Cmp(storage,"virtual")==0){
+	     Printf(interfaceBody, ", ");
+	  }
+	}
 	gencomma = 2;
 	Printf(function_code, "%s %s", param_type, arg);
+	// extract virtual function param type  for java interface
+	 if(Cmp(storage,"virtual")==0)
+	    Printf(interfaceBody, "%s %s", param_type, arg);

 	if (prematureGarbageCollectionPreventionParameter(pt, p)) {
           String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
@@ -2056,7 +2153,9 @@

     Printf(imcall, ")");
     Printf(function_code, ")");
-
+    if(Cmp(storage,"virtual")==0){
+       Printf(interfaceBody,")");
+    }
     // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function
(in proxy class)
     if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
       addThrows(n, "tmap:javaout", n);
@@ -2081,7 +2180,7 @@
 	Replaceall(tm, "$owner", "true");
       else
 	Replaceall(tm, "$owner", "false");
-      substituteClassname(t, tm);
+      substituteClassnameJavaout(t, tm);

       // For director methods: generate code to selectively make a normal polymorphic call or 
       // an explicit method call - needed to prevent infinite recursion calls in director methods.
@@ -2112,11 +2211,20 @@
     } else {
       Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap
defined for %s\n", SwigType_str(t, 0));
     }
-
+    
     generateThrowsClause(n, function_code);
+    
+    
     Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
+    if(Cmp(storage,"virtual")==0){
+       Printf(interfaceBody,";\n");
+    }
+   
     Printv(proxy_class_code, function_code, NIL);
-
+    //add the interface body into interface_code
+    if(Cmp(storage,"virtual")==0){
+       Printv(interface_code, interfaceBody, NIL);
+    }
     Delete(pre_code);
     Delete(post_code);
     Delete(function_code);
@@ -2122,6 +2230,7 @@
     Delete(function_code);
     Delete(return_type);
     Delete(imcall);
+    Delete(interfaceBody);
   }

   /* ----------------------------------------------------------------------
@@ -2158,8 +2267,13 @@

       tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
       Printf(im_return_type, "%s", tm);
-
-      Printf(function_code, "  %s %s(", methodmods, proxy_class_name);
+      if(!isInterface(interfaces_list,proxy_class_name)){
+         Printf(function_code, "  %s %s(", methodmods, proxy_class_name);
+      }else{
+    	  //if the class is a interface in java,we also need the concrete class with another name
+    	  String* ctorName=NewStringf("SWIGTYPE_%s",proxy_class_name);
+    	  Printf(function_code, "  %s %s(", methodmods, ctorName);
+      }
       Printf(helper_code, "  static private %s SwigConstruct%s(", im_return_type, proxy_class_name);

       Printv(imcall, imclass_name, ".", mangled_overname, "(", NIL);
@@ -2266,9 +2380,14 @@
       generateThrowsClause(n, function_code);

       /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
+     
       Hash *attributes = NewHash();
-      String *construct_tm = Copy(typemapLookup("javaconstruct", Getattr(n, "name"),
-						WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
+     
+      
+      String * construct_tm = Copy(typemapLookup("javaconstruct", Getattr(n,"name"),
+    	 						WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
+    	  
+           
       if (construct_tm) {
 	if (!feature_director) {
 	  Replaceall(construct_tm, "$directorconnect", "");
@@ -2303,16 +2422,18 @@
           Printv(helper_code, "    return ", imcall, ";", NIL);
         }
         Printf(helper_code, "\n  }\n");
-        String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
+           String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
+     
         Printv(proxy_class_code, helper_code, "\n", NIL);
         Replaceall(function_code, "$imcall", helper_name);
+        
         Delete(helper_name);
       } else {
         Replaceall(function_code, "$imcall", imcall);
+        
       }

       Printv(proxy_class_code, function_code, "\n", NIL);
-
       Delete(helper_args);
       Delete(im_return_type);
       Delete(pre_code);
@@ -2433,7 +2554,7 @@
     /* Get return types */
     if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
       substituteClassname(t, tm);
-      Printf(return_type, "%s", tm);
+        Printf(return_type, "%s", tm);
     } else {
       Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined
for %s\n", SwigType_str(t, 0));
     }
@@ -2480,7 +2601,7 @@
       /* Get the Java parameter type */
       if ((tm = Getattr(p, "tmap:jstype"))) {
 	substituteClassname(pt, tm);
-	Printf(param_type, "%s", tm);
+	  Printf(param_type, "%s", tm);
       } else {
 	Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap
defined for %s\n", SwigType_str(pt, 0));
       }
@@ -2566,7 +2687,7 @@
 	Replaceall(tm, "$owner", "true");
       else
 	Replaceall(tm, "$owner", "false");
-      substituteClassname(t, tm);
+      substituteClassnameJavaout(t, tm);
       Replaceall(tm, "$jnicall", imcall);
     } else {
       Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap
defined for %s\n", SwigType_str(t, 0));
@@ -2727,6 +2848,42 @@
     return substitution_performed;
   }

+  /*
+   * substituteClassnameJavaout()
+   * almost same as substituteClassname(),it is used replace the $javaclassname in javaout
+   * when the SwigType is declared as interface through %feature("interface")
+   */
+  bool substituteClassnameJavaout(SwigType *pt, String *tm, bool jnidescriptor = false) {
+      bool substitution_performed = false;
+      SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+      SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+      if (Strstr(tm, "$javaclassname")) {
+        SwigType *classnametype = Copy(strippedtype);
+        substituteClassnameSpecialVariableJavaout(classnametype, tm, "$javaclassname", jnidescriptor);
+        substitution_performed = true;
+        Delete(classnametype);
+      }
+      if (Strstr(tm, "$*javaclassname")) {
+        SwigType *classnametype = Copy(strippedtype);
+        Delete(SwigType_pop(classnametype));
+        substituteClassnameSpecialVariableJavaout(classnametype, tm, "$*javaclassname", jnidescriptor);
+        substitution_performed = true;
+        Delete(classnametype);
+      }
+      if (Strstr(tm, "$&javaclassname")) {
+        SwigType *classnametype = Copy(strippedtype);
+        SwigType_add_pointer(classnametype);
+        substituteClassnameSpecialVariableJavaout(classnametype, tm, "$&javaclassname", jnidescriptor);
+        substitution_performed = true;
+        Delete(classnametype);
+      }
+
+      Delete(strippedtype);
+      Delete(type);
+
+      return substitution_performed;
+    }
   /* -----------------------------------------------------------------------------
    * substituteClassnameSpecialVariable()
    * ----------------------------------------------------------------------------- */
@@ -2740,8 +2897,12 @@
 	Replaceall(tm, classnamespecialvariable, NewStringf("int"));
     } else {
       String *classname = getProxyName(classnametype);
+     
       if (classname) {
-	Replaceall(tm, classnamespecialvariable, classname);	// getProxyName() works for pointers to
classes too
+    	  
+	          Replaceall(tm, classnamespecialvariable, classname);	// getProxyName() works for pointers to
classes too
+	          
+    	 
       } else {			// use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
 	String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
 	Replaceall(tm, classnamespecialvariable, descriptor);
@@ -2752,7 +2913,39 @@
       }
     }
   }
+/*
+ * substituteClassnameSpecialVariableJavaout
+ */
+  void substituteClassnameSpecialVariableJavaout(SwigType *classnametype, String *tm, const char
*classnamespecialvariable, bool jnidescriptor) {
+      if (SwigType_isenum(classnametype)) {
+        String *enumname = getEnumName(classnametype, jnidescriptor);
+        if (enumname)
+  	Replaceall(tm, classnamespecialvariable, enumname);
+        else
+  	Replaceall(tm, classnamespecialvariable, NewStringf("int"));
+      } else {
+        String *classname = getProxyName(classnametype);
+       
+        if (classname) {
+      	  
+        	 if(!isInterface(interfaces_list,classname)){
+        		          Replaceall(tm, classnamespecialvariable, classname);	// getProxyName() works for pointers to
classes too
+        		          
+        	    	  }else{
+        	    		  classname=NewStringf("SWIGTYPE_%s",classname);
+        	    		  Replaceall(tm, classnamespecialvariable, classname);
+        	    	  }
+      	
+        } else {			// use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+  	String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+  	Replaceall(tm, classnamespecialvariable, descriptor);

+  	// Add to hash table so that the type wrapper classes can be created later
+  	Setattr(swig_types_hash, descriptor, classnametype);
+  	Delete(descriptor);
+        }
+      }
+    }
   /* -----------------------------------------------------------------------------
    * makeParameterName()
    *
Attachment (multiple_inheritance_abstract.i): application/octet-stream, 1805 bytes
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

Gmane