diff --git a/SWIG/Examples/test-suite/java/Makefile.in b/SWIG/Examples/test-suite/java/Makefile.in index 642d87e81..9d47fdc33 100644 --- a/SWIG/Examples/test-suite/java/Makefile.in +++ b/SWIG/Examples/test-suite/java/Makefile.in @@ -18,6 +18,7 @@ CPP_TEST_CASES = \ enum_thorough_simple \ enum_thorough_typeunsafe \ java_constants \ + java_director \ java_enums \ java_lib_arrays_dimensionless \ java_lib_various \ diff --git a/SWIG/Examples/test-suite/java/java_director_runme.java b/SWIG/Examples/test-suite/java/java_director_runme.java new file mode 100644 index 000000000..850bf8bf3 --- /dev/null +++ b/SWIG/Examples/test-suite/java/java_director_runme.java @@ -0,0 +1,75 @@ +// Mainly tests that directors are finalized correctly + +import java_director.*; + +public class java_director_runme { + + static { + try { + System.loadLibrary("java_director"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + QuuxContainer qc = createContainer(); + + int instances = Quux.instances(); + if (instances != 4) + throw new RuntimeException("Quux instances should be 4, actually " + instances); + + for (int i = 0; i < qc.size(); ++i) { + Quux q = qc.get(i); + + if (!q.director_method().equals(qc.invoke(i))) { + throw new RuntimeException ( "q.director_method()/qv.invoke(" + i + ")"); + } + } + + qc = null; + /* Watch qc get reaped, which causes the C++ object to delete + objects from the internal vector */ + System.gc(); + System.runFinalization(); + + /* Watch the Quux objects formerly in the QuuxContainer object + get reaped */ + System.gc(); + System.runFinalization(); + + instances = Quux.instances(); + if (instances != 0) + throw new RuntimeException("Quux instances should be 0, actually " + instances); + + /* Test Quux1's director disconnect method rename */ + Quux1 quux1 = new Quux1("quux1"); + if (quux1.disconnectMethodCalled) + throw new RuntimeException("Oops"); + quux1.delete(); + if (!quux1.disconnectMethodCalled) + throw new RuntimeException("disconnect method not called"); + } + + public static QuuxContainer createContainer() { + QuuxContainer qc = new QuuxContainer(); + + qc.push(new Quux("element 1")); + qc.push(new MyQuux("element 2")); + qc.push(new MyQuux("element 3")); + qc.push(new Quux("element 4")); + + return qc; + } +} + +class MyQuux extends Quux { + public MyQuux(String arg) { + super(arg); + } + + public String director_method() { + return "MyQuux:" + member(); + } +} diff --git a/SWIG/Examples/test-suite/java_director.i b/SWIG/Examples/test-suite/java_director.i new file mode 100644 index 000000000..dd8fa9455 --- /dev/null +++ b/SWIG/Examples/test-suite/java_director.i @@ -0,0 +1,115 @@ +/* + * Test Java director typemaps and features + */ + +%module(directors="1") java_director + +%typemap(javafinalize) SWIGTYPE %{ + protected void finalize() { +// System.out.println("Finalizing " + this); + delete(); + } +%} + + +%{ +#include +#include + +class Quux { +public: + Quux() : memb_("default Quux ctor arg") {instances_++; } + Quux(const std::string &arg) : memb_(arg) {instances_++;} + Quux(const Quux &src) : memb_(src.memb_) {instances_++;} + virtual ~Quux() {instances_--;} + virtual const std::string &director_method() { return memb_; } + const std::string &member() { return memb_; } + static int instances() { return instances_; } +private: + static int instances_; + std::string memb_; +}; + +int Quux::instances_ = 0; + +class QuuxContainer { +protected: + typedef std::vector quuxvec_t; +public: + QuuxContainer() : quuxen_() + { } + ~QuuxContainer() { + for (quuxvec_t::iterator iter = quuxen_.begin(); iter != quuxen_.end(); ++iter) { + delete *iter; + } + quuxen_.clear(); + } + void push(Quux *elem) { + quuxen_.push_back(elem); + } + Quux *get(int idx) { + return quuxen_[idx]; + } + const std::string &invoke(int idx) { + return quuxen_[idx]->director_method(); + } + int size() { + return quuxen_.size(); + } +private: + quuxvec_t quuxen_; +}; +%} + +%include "std_string.i" + +%feature("director") Quux; +SWIG_DIRECTOR_OWNED(Quux) + +class Quux { +public: + Quux(); + Quux(const std::string &arg); + Quux(const Quux &src); + virtual ~Quux(); + virtual const std::string &director_method(); + const std::string &member(); + static int instances(); +}; + +class QuuxContainer { +public: + QuuxContainer(); + ~QuuxContainer(); + void push(Quux *elem); + Quux *get(int idx); + const std::string &invoke(int idx); + int size(); +}; + + +%feature("director"); + +%typemap(javacode) hi::Quux1 %{ + public boolean disconnectMethodCalled = false; +%} + +%typemap(directordisconnect_derived, methodname="disconnect_director") hi::Quux1 { + swigCMemOwn = false; + $jnicall; + // add in a flag to check this method is really called + disconnectMethodCalled = true; + } + +%inline %{ + +namespace hi { + struct Quux1 : public Quux { + Quux1(const std::string& arg) : Quux(arg) {} + virtual int ff(int i = 0) {return i;} + }; +} + + +%} +