diff --git a/SWIG/Examples/test-suite/director_abstract.i b/SWIG/Examples/test-suite/director_abstract.i index 6e79178d2..9fc8151ab 100644 --- a/SWIG/Examples/test-suite/director_abstract.i +++ b/SWIG/Examples/test-suite/director_abstract.i @@ -1,4 +1,4 @@ -%module(directors="1") director_abstract +%module(directors="1",dirprot="1") director_abstract %{ #include @@ -17,36 +17,122 @@ public: class Foo { public: - virtual ~Foo() {} - virtual std::string ping() = 0; - virtual std::string pong() { return "Foo::pong();" + ping(); } + virtual ~Foo() {} + virtual std::string ping() = 0; + virtual std::string pong() { return "Foo::pong();" + ping(); } }; -%feature("director") Example1; +%feature("director"); %inline %{ -class Example1 +class Example0 { -private: - protected: - int xsize, ysize; - int fontsize; - int fontdim[23]; + int xsize, ysize; + +public: + + Example0(int x, int y) + : xsize(x), ysize(y) { } + Example0() { } public: - Example1() - : xsize(200), ysize(200) { } + virtual ~Example0() {} + + int GetXSize() const { return xsize; } + + // pure virtual methods that must be overridden + virtual int Color(unsigned char r, unsigned char g, unsigned char b) + { + return 0; + } + - virtual ~Example1() {} - - int GetXSize() const { return xsize; } - - // pure virtual methods that must be overridden - virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0; + static int get_color(Example0 *ptr, unsigned char r, + unsigned char g, unsigned char b) { + return ptr->Color(r, g, b); + } }; +class Example1 +{ +protected: + int xsize, ysize; + +public: + + Example1(int x, int y) + : xsize(x), ysize(y) { } + + Example1() { } + +public: + virtual ~Example1() {} + + int GetXSize() const { return xsize; } + + // pure virtual methods that must be overridden + virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0; + + static int get_color(Example1 *ptr, unsigned char r, + unsigned char g, unsigned char b) { + return ptr->Color(r, g, b); + } + + +}; + + +class Example2 +{ +protected: + int xsize, ysize; + +protected: + Example2(int x, int y) + : xsize(x), ysize(y) { } + +public: + + virtual ~Example2() {} + + int GetXSize() const { return xsize; } + + // pure virtual methods that must be overridden + virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0; + + static int get_color(Example2 *ptr, unsigned char r, + unsigned char g, unsigned char b) { + return ptr->Color(r, g, b); + } +}; + +namespace ns +{ + template + class Example3 + { + public: + Example3() + { + } + + Example3(int x, int y) { } + + virtual ~Example3() {} + + // pure virtual methods that must be overridden + virtual int Color(unsigned char r, unsigned char g, unsigned char b) = 0; + + static int get_color(Example3 *ptr, unsigned char r, + unsigned char g, unsigned char b) { + return ptr->Color(r, g, b); + } + }; +} %} + +%template(Example3_i) ns::Example3; diff --git a/SWIG/Examples/test-suite/python/director_abstract_runme.py b/SWIG/Examples/test-suite/python/director_abstract_runme.py index 042b72f41..df8a2fa44 100644 --- a/SWIG/Examples/test-suite/python/director_abstract_runme.py +++ b/SWIG/Examples/test-suite/python/director_abstract_runme.py @@ -16,15 +16,47 @@ if a.pong() != "Foo::pong();MyFoo::ping()": raise RuntimeError, a.pong() -class MyExample(director_abstract.Example1): - def __init__(self): - director_abstract.Example1.__init__(self) - pass - +class MyExample1(director_abstract.Example1): def Color(self, r, g, b): return r -me = MyExample() +class MyExample2(director_abstract.Example2): + def Color(self, r, g, b): + return g -print me.Color(1,2,3) +class MyExample3(director_abstract.Example3_i): + def Color(self, r, g, b): + return b +me1 = MyExample1() +if MyExample1.get_color(me1, 1,2,3) != 1: + raise RuntimeError + +me2 = MyExample2(1,2) +if MyExample2.get_color(me2, 1,2,3) != 2: + raise RuntimeError + +me3 = MyExample3() +if MyExample3.get_color(me3, 1,2,3) != 3: + raise RuntimeError + +error = 1 +try: + me1 = director_abstract.Example1() +except: + error = 0 +if (error): raise RuntimeError + +error = 1 +try: + me2 = director_abstract.Example2() +except: + error = 0 +if (error): raise RuntimeError + +error = 1 +try: + me3 = director_abstract.Example3_i() +except: + error = 0 +if (error): raise RuntimeError diff --git a/SWIG/Examples/test-suite/ruby/director_abstract_runme.rb b/SWIG/Examples/test-suite/ruby/director_abstract_runme.rb index f303b544b..29f697866 100644 --- a/SWIG/Examples/test-suite/ruby/director_abstract_runme.rb +++ b/SWIG/Examples/test-suite/ruby/director_abstract_runme.rb @@ -18,3 +18,14 @@ if a.pong != "Foo::pong();MyFoo::ping()" end +class MyExample1 < Director_abstract::Example1 + def color(r,g,b) + r + end +end + +#m1 = MyExample1.new +# +#if m1.color(1,2,3) != 1 +# raise RuntimeError, m1.color +#end diff --git a/SWIG/Source/Include/swigwarn.h b/SWIG/Source/Include/swigwarn.h index d29fe0435..97213fc20 100644 --- a/SWIG/Source/Include/swigwarn.h +++ b/SWIG/Source/Include/swigwarn.h @@ -164,6 +164,7 @@ #define WARN_LANG_DIRECTOR_VDESTRUCT 514 #define WARN_LANG_DISCARD_CONST 515 #define WARN_LANG_OVERLOAD_IGNORED 516 +#define WARN_LANG_DIRECTOR_ABSTRACT 517 /* -- Reserved (600-799) -- */ diff --git a/SWIG/Source/Modules/lang.cxx b/SWIG/Source/Modules/lang.cxx index 6f5911356..14704b34c 100644 --- a/SWIG/Source/Modules/lang.cxx +++ b/SWIG/Source/Modules/lang.cxx @@ -248,10 +248,12 @@ int Dispatcher::accessDeclaration(Node *n) { return defaultHandler(n); } int Dispatcher::usingDeclaration(Node *n) { return defaultHandler(n); } int Dispatcher::namespaceDeclaration(Node *n) { return defaultHandler(n); } + /* Allocators */ Language::Language() : none_comparison(NewString("$arg != 0")), director_ctor_code(NewString("")), + director_prot_ctor_code(0), symbols(NewHash()), classtypes(NewHash()), enumtypes(NewHash()), @@ -270,6 +272,11 @@ Language::Language() : " $nondirector_new \n", "}\n", NIL); + /* + Default director 'protected' constructor code, disable by + default. Each language that need it, has to define it. + */ + director_prot_ctor_code = 0; } Language::~Language() { @@ -1665,7 +1672,7 @@ int Language::classDirectorConstructors(Node *n) { for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { nodeType = Getattr(ni, "nodeType"); if (!Cmp(nodeType, "constructor")) { - if (is_public(ni)) { + if (is_public(ni) || (dirprot_mode() && is_protected(ni))) { classDirectorConstructor(ni); constructor = 1; } @@ -1960,6 +1967,7 @@ int Language::classHandler(Node *n) { Iterator k; int old_mode = cplus_mode; cplus_mode = CPLUS_PROTECTED; + for (k = First(vtable); k.key; k = Next(k)) { item = k.item; Node *method = Getattr(item, "methodNode"); @@ -2002,9 +2010,22 @@ int Language::constructorDeclaration(Node *n) { String *symname = Getattr(n,"sym:name"); if (!CurrentClass) return SWIG_NOWRAP; - if (cplus_mode != CPLUS_PUBLIC) return SWIG_NOWRAP; if (ImportMode) return SWIG_NOWRAP; + int need_prot = 0; + if ((cplus_mode != CPLUS_PUBLIC) && directorsEnabled()) { + need_prot = director_prot_ctor_code && dirprot_mode() + && Swig_directorclass(CurrentClass) && is_protected(n); + if (need_prot) { + Node *parent = Swig_methodclass(n); + name = Getattr(parent,"name"); + symname = Getattr(parent,"sym:name"); + Setattr(n,"name",name); + Setattr(n,"sym:name",symname); + } + } + if ((cplus_mode != CPLUS_PUBLIC) && !need_prot) return SWIG_NOWRAP; + /* Name adjustment for %name */ Swig_save("constructorDeclaration",n,"sym:name",NIL); @@ -2067,7 +2088,18 @@ Language::constructorHandler(Node *n) { Swig_require("constructorHandler",n,"?name","*sym:name","?type","?parms",NIL); String *symname = Getattr(n,"sym:name"); String *mrename = Swig_name_construct(symname); - Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor_code, CPlusPlus, Getattr(n, "template") ? 0 :Extend); + String *director_ctor = director_ctor_code; + if (!is_public(n)) { + if (director_prot_ctor_code && is_protected(n)) { + director_ctor = director_prot_ctor_code; + } + } + if (Getattr(Swig_methodclass(n),"abstract")) { + if (director_prot_ctor_code) { + director_ctor = director_prot_ctor_code; + } + } + Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 :Extend); Setattr(n,"sym:name", mrename); functionWrapper(n); Delete(mrename); @@ -2554,9 +2586,30 @@ String * Language::getClassType() const { * ----------------------------------------------------------------------------- */ int Language::abstractClassTest(Node *n) { - return (Getattr(n,"abstract") ? 1 : 0); + List *abstract = Getattr(n,"abstract"); + if (!abstract) return 0; + if (abstract && Cmp(Getattr(n, "feature:director"), "1")) return 1; + /* + since now %feature("noabstract") is working, we check + that the director is really not abstract. + */ + int dirabstract = 0; + for (int i = 0; i < Len(abstract); i++) { + Node *nn = Getitem(abstract,i); + if (!is_member_director(n,nn)) { + dirabstract = 1; + } + } + if (dirabstract) { + Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT,Getfile(n),Getline(n), + "Director class '%s' is abstract\n", + SwigType_namestr(Getattr(n,"name"))); + } + + return dirabstract; } + void Language::setSubclassInstanceCheck(String *nc) { none_comparison = nc; } diff --git a/SWIG/Source/Modules/ocaml.cxx b/SWIG/Source/Modules/ocaml.cxx index f9c475c2f..3c4a8bba2 100755 --- a/SWIG/Source/Modules/ocaml.cxx +++ b/SWIG/Source/Modules/ocaml.cxx @@ -68,6 +68,18 @@ static File *f_int_to_enum = 0; class OCAML : public Language { public: + OCAML() + { + director_prot_ctor_code = NewString(""); + Printv(director_prot_ctor_code, + "if ( $comparison ) { /* subclassed */\n", + " $director_new \n", + "} else {\n", + " failwith(\"accessing abstract class or protected constructor\"); \n", + "}\n", NIL); + } + + String *Swig_class_name(Node *n) { String *name; name = Copy(Getattr(n, "sym:name")); diff --git a/SWIG/Source/Modules/python.cxx b/SWIG/Source/Modules/python.cxx index 1247dae18..fade6f81e 100644 --- a/SWIG/Source/Modules/python.cxx +++ b/SWIG/Source/Modules/python.cxx @@ -82,7 +82,20 @@ Python Options (available with -python)\n\ class PYTHON : public Language { public: - + PYTHON() + { + /* Add code to manage protected constructors and directors */ + director_prot_ctor_code = NewString(""); + Printv(director_prot_ctor_code, + "if ( $comparison ) { /* subclassed */\n", + " $director_new \n", + "} else {\n", + " PyErr_SetString(PyExc_RuntimeError,", + " \"accessing abstract class or protected constructor\"); \n", + " SWIG_fail;\n", + "}\n", NIL); + } + /* ------------------------------------------------------------ * main() * ------------------------------------------------------------ */ diff --git a/SWIG/Source/Modules/ruby.cxx b/SWIG/Source/Modules/ruby.cxx index 4232a7a99..4a16efe73 100644 --- a/SWIG/Source/Modules/ruby.cxx +++ b/SWIG/Source/Modules/ruby.cxx @@ -187,6 +187,15 @@ public: f_init = 0; useGlobalModule = false; multipleInheritance = false; + + director_prot_ctor_code = NewString(""); + Printv(director_prot_ctor_code, + "if ( $comparison ) { /* subclassed */\n", + " $director_new \n", + "} else {\n", + " rb_raise(rb_eRuntimeError,\"accessing abstract class or protected constructor\"); \n", + " result = 0;\n", + "}\n", NIL); } /* --------------------------------------------------------------------- @@ -622,15 +631,15 @@ public: String *s = NewString(""); String *temp = NewString(""); +#ifdef SWIG_PROTECTED_TARGET_METHODS + const char* rb_define_method = is_public(n) ? + "rb_define_method" : "rb_define_protected_method" ; +#else + const char* rb_define_method = "rb_define_method"; +#endif switch (current) { case MEMBER_FUNC: { -#ifdef SWIG_PROTECTED_TARGET_METHODS - const char* rb_define_method = is_public(n) ? - "rb_define_method" : "rb_define_protected_method" ; -#else - const char* rb_define_method = "rb_define_method"; -#endif if (multipleInheritance) { Printv(klass->init, tab4, rb_define_method,"(", klass->mImpl, ", \"", iname, "\", ", wname, ", -1);\n", NIL); @@ -645,7 +654,7 @@ public: Replaceall(klass->init,"$allocator", s); break; case CONSTRUCTOR_INITIALIZE: - Printv(s, tab4, "rb_define_method(", klass->vname, + Printv(s, tab4, rb_define_method,"(", klass->vname, ", \"initialize\", ", wname, ", -1);\n", NIL); Replaceall(klass->init,"$initializer", s); break; diff --git a/SWIG/Source/Modules/swigmod.h b/SWIG/Source/Modules/swigmod.h index dca951986..c3c5ccbff 100644 --- a/SWIG/Source/Modules/swigmod.h +++ b/SWIG/Source/Modules/swigmod.h @@ -269,6 +269,9 @@ public: /* Director constructor "template" code */ String *director_ctor_code; + /* Director 'protected' constructor "template" code*/ + String *director_prot_ctor_code; + private: Hash *symbols; Hash *classtypes;