diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 283a1cff2..734f980ab 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -47,8 +47,6 @@ DYNAMIC_LIB_PATH = $(RUNTIMEDIR):. CPP_TEST_BROKEN += \ array_typedef_memberin \ defvalue_constructor \ - director_nested \ - director_protected \ exception_order \ namespace_union \ smart_pointer_namespace2 \ @@ -116,6 +114,8 @@ CPP_TEST_CASES += \ director_finalizer \ director_unroll \ director_wombat \ + director_nested \ + director_protected \ dynamic_cast \ enum_plus \ enum_scope \ diff --git a/Examples/test-suite/director_nested.i b/Examples/test-suite/director_nested.i index 6b6ec9f2c..81762a224 100644 --- a/Examples/test-suite/director_nested.i +++ b/Examples/test-suite/director_nested.i @@ -47,14 +47,14 @@ } - virtual std::string do_step() = 0; + virtual std::string do_step() const = 0; }; template class FooBar : public Bar { public: - virtual C get_value() = 0; + virtual C get_value() const = 0; }; %} diff --git a/Examples/test-suite/python/director_protected_runme.py b/Examples/test-suite/python/director_protected_runme.py index 66559068c..9314f5845 100644 --- a/Examples/test-suite/python/director_protected_runme.py +++ b/Examples/test-suite/python/director_protected_runme.py @@ -35,20 +35,20 @@ try: except: raise RuntimeError," bad FooBar::pong" -private=1 +protected=1 try: b.ping() - private=0 + protected=0 except: pass -if not private: - raise RuntimeError,"Boo::ping is private" +if not protected: + raise RuntimeError,"Boo::ping is protected" -private=1 +protected=1 try: f.ping() - private=0 + protected=0 except: pass -if not private: - raise RuntimeError,"Foo::ping is private" +if not protected: + raise RuntimeError,"Foo::ping is protected" diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 46267e803..754274561 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -13,6 +13,7 @@ * ----------------------------------------------------------------------------- */ #include "swigmod.h" +#include "utils.h" char cvsroot_emit_cxx[] = "$Header$"; @@ -366,6 +367,27 @@ void emit_action(Node *n, Wrapper *f) { action = Getattr(n,"wrap:action"); assert(action != 0); + if (is_protected(n) && is_member_director(n)) { + /* We need to add an extra dynamic_cast to + access the director class, where the virtual + methods are all public */ + Node* parent = Getattr(n,"parentNode"); + String* symname = Getattr(parent, "sym:name"); + String* classtype = Getattr(parent,"classtype"); + String* dirname = NewStringf("SwigDirector_%s", symname); + String* dirdecl = NewStringf("%s *darg1 = 0", dirname); + Wrapper_add_local(f, "darg1", dirdecl); + Printf(f->code, "darg1 = dynamic_cast<%s *>(arg1);\n",dirname); + /* Maybe here a more detailed diagnostic can de added, + such as trying to access a protected member, but it seems + it is not easy to do it for all the languages at once*/ + Printf(f->code, "if (!darg1) return NULL;\n"); + Replaceall(action,"arg1","darg1"); + Replaceall(action,classtype,dirname); + Delete(dirname); + Delete(dirdecl); + } + /* Get the return type */ rt = Getattr(n,"type"); diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 87df48277..1f29bc575 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -697,8 +697,11 @@ int Language::cDeclaration(Node *n) { File *f_header = 0; SwigType *ty, *fullty; - if (CurrentClass && (cplus_mode != CPLUS_PUBLIC)) return SWIG_NOWRAP; - + + if (CurrentClass && (cplus_mode == CPLUS_PRIVATE)) return SWIG_NOWRAP; + if ((cplus_mode == CPLUS_PROTECTED) && + (!director_protected_mode || !is_member_director(CurrentClass,n))) return SWIG_NOWRAP; + if (Cmp(storage,"typedef") == 0) { Swig_save("cDeclaration",n,"type",NIL); SwigType *t = Copy(type); @@ -1712,7 +1715,36 @@ int Language::classHandler(Node *n) { /* emit director disown method */ if (hasDirector) { - classDirectorDisown(n); + classDirectorDisown(n); + + /* emit all the protected virtual members as needed */ + Node *vtable = Getattr(n, "vtable"); + String* symname = Getattr(n, "sym:name"); + Node *item; + Iterator k; + int old_mode = cplus_mode; + cplus_mode = CPLUS_PROTECTED; + for (k = First(vtable); k.key; k = Next(k)) { + item = k.item; + String* director = Getattr(item,"director"); + Node *method = Getattr(item, "methodNode"); + Node* parentnode = Getattr(method, "parentNode"); + String* methodname = Getattr(method,"sym:name"); + String* wrapname = NewStringf("%s_%s", symname,methodname); + if (!Getattr(symbols,wrapname) + && !Cmp(director,"1") + && (n != parentnode) + && is_protected(method)) { + Node* m = Copy(method); + Setattr(m,"parentNode", n); + /* ugly trick, to avoid an uglier one later on emit.*/ + Replace(Getattr(m,"decl"),"q(const).","",1); + cDeclaration(m); + Delete(m); + } + Delete(wrapname); + } + cplus_mode = old_mode; } return SWIG_OK; diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 400be8fe1..90fea56da 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -72,6 +72,7 @@ static char *usage = (char*)"\ -module - Set module name to \n\ -nocontract - Turn off contract checking \n\ -nodefault - Do not generate constructors/destructors\n\ + -nodirprot - Do not wrap director protected members\n\ -noexcept - Do not wrap exception specifiers\n\ -noextern - Do not generate extern declarations\n\ -noruntime - Do not include SWIG runtime code\n\ @@ -201,7 +202,7 @@ extern "C" Node *Swig_cparse(File *); extern "C" void Swig_cparse_cplusplus(int); extern "C" void Swig_cparse_debug_templates(int); extern void Wrapper_virtual_elimination_mode_set(int); - +extern void Wrapper_director_protected_mode_set(int); extern void Swig_contracts(Node *n); extern void Swig_contract_mode_set(int flag); @@ -280,6 +281,10 @@ int SWIG_main(int argc, char *argv[], Language *l) { Swig_contract_mode_set(1); Preprocessor_define(vers,0); + /* Turn on director protected mode */ + Wrapper_director_protected_mode_set(1); + + // Check for SWIG_LIB environment variable if ((c = getenv("SWIG_LIB")) == (char *) 0) { @@ -322,6 +327,8 @@ int SWIG_main(int argc, char *argv[], Language *l) { Wrapper_compact_print_mode_set(1); } else if (strcmp(temp, "-fvirtual") == 0) { Wrapper_virtual_elimination_mode_set(1); + } else if (strcmp(temp,"-nodirprot") == 0) { + Wrapper_director_protected_mode_set(0); } else if (strcmp(temp, "-small") == 0) { Wrapper_compact_print_mode_set(1); Wrapper_virtual_elimination_mode_set(1); @@ -360,6 +367,8 @@ int SWIG_main(int argc, char *argv[], Language *l) { } else if (strcmp(argv[i],"-fvirtual") == 0) { Wrapper_virtual_elimination_mode_set(1); Swig_mark_arg(i); + } else if (strcmp(argv[i],"-nodirprot") == 0) { + Wrapper_director_protected_mode_set(0); } else if (strcmp(argv[i],"-small") == 0) { Wrapper_compact_print_mode_set(1); Wrapper_virtual_elimination_mode_set(1); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 300e5a9a6..cf452c7ba 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -12,7 +12,6 @@ char cvsroot_python_cxx[] = "$Header$"; #include "swigmod.h" -#include "utils.h" #ifndef MACSWIG #include "swigconfig.h" @@ -67,11 +66,8 @@ Python Options (available with -python)\n\ -apply - Use apply() in proxy classes\n\ -new_repr - Use more informative version of __repr__ in proxy classes\n\ -noexcept - No automatic exception handling\n\ - -nodirprot - Don't wrap director protected members\n\ -noproxy - Don't generate proxy classes \n\n"; -extern void Wrapper_director_protected_mode_set(int); - class PYTHON : public Language { public: @@ -83,8 +79,6 @@ public: SWIG_library_directory("python"); - Wrapper_director_protected_mode_set(1); - for (int i = 1; i < argc; i++) { if (argv[i]) { if(strcmp(argv[i],"-interface") == 0) { @@ -128,8 +122,6 @@ public: classic = 0; modern = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i],"-nodirprot") == 0) { - Wrapper_director_protected_mode_set(0); } else if (strcmp(argv[i],"-help") == 0) { fputs(usage,stderr); } else if (strcmp (argv[i], "-ldflags") == 0) { @@ -1313,13 +1305,7 @@ public: Wrapper_add_local(w, "result", "PyObject *result"); /* direct call to superclass if _up is set */ - if (is_protected(n)) { - Printf(w->code, "PyObject *obj = PyObject_GetAttrString(swig_get_self(), \"%s\");\n", - Getattr(n,"sym:name")); - Printf(w->code, "if (!obj) {\n"); - } else { - Printf(w->code, "if (swig_get_up()) {\n"); - } + Printf(w->code, "if (swig_get_up()) {\n"); if (pure_virtual) { Printf(w->code, "throw Swig::DirectorPureVirtualException();\n"); } else { diff --git a/Source/Modules/utils.h b/Source/Modules/utils.h index 29b7c6cc2..c86123b53 100644 --- a/Source/Modules/utils.h +++ b/Source/Modules/utils.h @@ -24,12 +24,17 @@ int is_protected(Node* n) } inline -int is_member_director(Node* classnode, Node* member) +int is_member_director(Node* parentnode, Node* member) { - int class_director = !Cmp(Getattr(classnode,"feature:director"), "1"); + int parent_director = !Cmp(Getattr(parentnode,"feature:director"), "1"); int cdecl_nodirector = !Cmp(Getattr(member,"feature:nodirector"),"1"); - return class_director && !cdecl_nodirector; + return parent_director && !cdecl_nodirector; } +inline +int is_member_director(Node* member) +{ + return is_member_director(Getattr(member, "parentNode"), member); +} #endif //__Modules_utils_h__