diff --git a/SWIG/Examples/test-suite/refcount.i b/SWIG/Examples/test-suite/refcount.i index 0413e0eda..15ecad032 100644 --- a/SWIG/Examples/test-suite/refcount.i +++ b/SWIG/Examples/test-suite/refcount.i @@ -6,7 +6,7 @@ #include "refcount.h" %} -#if 1 +#if 0 // // the old macro way // @@ -32,8 +32,8 @@ RefCount(B); // using the ref/unref features you can active the ref. counting // for RCObj and all its descendents at once // -%feature("refbase") RCObj "$this->ref();" -%feature("unrefbase") RCObj "$this->unref();" +%feature("ref") RCObj "$this->ref();" +%feature("unref") RCObj "$this->unref();" #endif @@ -106,16 +106,8 @@ RefCount(B); /* Other ref/unref uses: -// deactive the refcounting for A1 +// deactive the refcounting for A1 and its descendents %feature("noref") A1; %feature("nounref") A1; -// deactive the refcounting for A2 and all its descendents -%feature("norefbase") A2; -%feature("nounrefbase") A2; - -// active the refcounting only for A3 -%feature("ref") A3 { $this->ref(); } -%feature("unref") A3 { $this->unref(); } - */ diff --git a/SWIG/Source/Swig/cwrap.c b/SWIG/Source/Swig/cwrap.c index fa20f0d97..0fd6106b9 100644 --- a/SWIG/Source/Swig/cwrap.c +++ b/SWIG/Source/Swig/cwrap.c @@ -395,6 +395,106 @@ Swig_cppconstructor_director_call(String_or_char *name, ParmList *parms) { return Swig_cppconstructor_base_call(name, parms, 0); } +/* ----------------------------------------------------------------------------- + * Swig_cattr_search() + * + * This function search for the class attribute 'attr' in the class + * 'n' or recursively in its bases. + * + * if you define SWIG_FAST_REC_SEARCH, the method will set the found + * 'attr' in io the target class 'n'. If not, the method will set the + * 'noattr' one. This prevents of having to navigate the entire + * hierarchy tree everytime, so, it is an O(1) method... or something + * like that. However, it populates all the parsed classes with the + * 'attr' and/or 'noattr' attributes. + * + * If you undefine the SWIG_FAST_REC_SEARCH no attribute will be set + * while searching. This could be slower for large projects with very + * large hierarchy trees... or maybe not. But it will be cleaner. + * + * Maybe latter a swig option can be added to switch at runtime. + * + * ----------------------------------------------------------------------------- */ + +/* #define SWIG_FAST_REC_SEARCH 1 */ +String * +Swig_cattr_search(Node *n, const String *attr, const String *noattr) +{ + String *f = 0; + n = Swig_methodclass(n); + if (Getattr(n, noattr)) { + /* Printf(stdout,"noattr in %s\n", Getattr(n,"name")); */ + return 0; + } + f = Getattr(n, attr); + if (f) { + /* Printf(stdout,"attr in %s\n", Getattr(n,"name")); */ + return f; + } else { + List* bl = Getattr(n, "bases"); + if (bl) { + Iterator bi; + for (bi = First(bl); bi.item; bi = Next(bi)) { + f = Swig_cattr_search(bi.item, attr, noattr); + if (f) { +#ifdef SWIG_FAST_REC_SEARCH + Setattr(n, attr, f); +#endif + return f; + } + } + } + } +#ifdef SWIG_FAST_REC_SEARCH + Setattr(n, noattr, "1"); +#endif + return 0; +} + +/* ----------------------------------------------------------------------------- + * Swig_unref_call() + * + * find the unref call, if any. + * ----------------------------------------------------------------------------- */ + +String * +Swig_unref_call(Node *n) { + String* unref = 0; + n = Swig_methodclass(n); + if (!Getattr(n,"feature:nounref")) { + unref = Getattr(n,"feature:unref"); + unref = unref ? unref : + Swig_cattr_search(n,"feature:unref","feature:nounref"); + if (unref) { + unref = NewStringf("%s",unref); + Replaceall(unref,"$this",Swig_cparm_name(0,0)); + } + } + return unref; +} + +/* ----------------------------------------------------------------------------- + * Swig_ref_call() + * + * find the ref call, if any. + * ----------------------------------------------------------------------------- */ + +String * +Swig_ref_call(Node *n, const String* lname) { + String* ref = 0; + n = Swig_methodclass(n); + if (!Getattr(n,"feature:noref")) { + ref = Getattr(n,"feature:ref"); + ref = ref ? ref : + Swig_cattr_search(n,"feature:ref","feature:noref"); + if (ref) { + ref = NewStringf("%s",ref); + Replaceall(ref,"$this",lname); + } + } + return ref; +} + /* ----------------------------------------------------------------------------- * Swig_cdestructor_call() * @@ -404,11 +504,11 @@ Swig_cppconstructor_director_call(String_or_char *name, ParmList *parms) { * ----------------------------------------------------------------------------- */ String * -Swig_cdestructor_call() { - String *func; - func = NewString(""); - Printf(func,"free((char *) %s)", Swig_cparm_name(0,0)); - return func; +Swig_cdestructor_call(Node *n) { + String* unref = Swig_unref_call(n); + if (unref) return unref; + + return NewStringf("free((char *) %s);",Swig_cparm_name(0,0)); } @@ -421,12 +521,11 @@ Swig_cdestructor_call() { * ----------------------------------------------------------------------------- */ String * -Swig_cppdestructor_call() { - String *func; +Swig_cppdestructor_call(Node *n) { + String* unref = Swig_unref_call(n); + if (unref) return unref; - func = NewString(""); - Printf(func,"delete %s", Swig_cparm_name(0,0)); - return func; + return NewStringf("delete %s;",Swig_cparm_name(0,0)); } /* ----------------------------------------------------------------------------- @@ -584,9 +683,11 @@ Swig_directormethod(Node *n) { if (vtable) { String *name = Getattr(n, "name"); String *decl = Getattr(n, "decl"); - String *method_id = NewStringf("%s|%s", name, decl); + String *local_decl = SwigType_typedef_resolve_all(decl); + String *method_id = NewStringf("%s|%s", name, local_decl); Hash *item = Getattr(vtable, method_id); Delete(method_id); + Delete(local_decl); if (item) { return (Getattr(item, "director") != 0); } @@ -789,11 +890,9 @@ Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags) Delete(mangled); } else { if (cplus) { - String* action = NewString(""); - Printf(action, "%s;\n", Swig_cppdestructor_call()); - Setattr(n,"wrap:action", action); + Setattr(n,"wrap:action", NewStringf("%s\n",Swig_cppdestructor_call(n))); } else { - Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cdestructor_call())); + Setattr(n,"wrap:action", NewStringf("%s\n", Swig_cdestructor_call(n))); } } Setattr(n,"type",type); diff --git a/SWIG/Source/Swig/swig.h b/SWIG/Source/Swig/swig.h index 2da19154c..87e49cace 100644 --- a/SWIG/Source/Swig/swig.h +++ b/SWIG/Source/Swig/swig.h @@ -447,8 +447,10 @@ extern String *Swig_cfunction_call(String_or_char *name, ParmList *parms); extern String *Swig_cmethod_call(String_or_char *name, ParmList *parms, String_or_char *self); extern String *Swig_cconstructor_call(String_or_char *name); extern String *Swig_cppconstructor_call(String_or_char *name, ParmList *parms); -extern String *Swig_cdestructor_call(); -extern String *Swig_cppdestructor_call(); +extern String *Swig_unref_call(Node *n); +extern String *Swig_ref_call(Node *n, const String* lname); +extern String *Swig_cdestructor_call(Node *n); +extern String *Swig_cppdestructor_call(Node *n); extern String *Swig_cmemberset_call(String_or_char *name, SwigType *type, String_or_char *self); extern String *Swig_cmemberget_call(const String_or_char *name, SwigType *t, String_or_char *self); diff --git a/SWIG/Source/Swig/typemap.c b/SWIG/Source/Swig/typemap.c index 962af4251..38a9fbf5e 100644 --- a/SWIG/Source/Swig/typemap.c +++ b/SWIG/Source/Swig/typemap.c @@ -1107,6 +1107,7 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri String *pname; Hash *tm; String *s = 0; + String *sdef = 0; ParmList *locals; ParmList *kw; char temp[256]; @@ -1114,18 +1115,24 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri String *cname = 0; String *clname = 0; + /* special case, we need to check for 'ref' call + and set the defaul code 'sdef' */ + if (Cmp(op,"newfree") == 0) { + sdef = Swig_ref_call(node, lname); + } + type = Getattr(node,"type"); - if (!type) return 0; + if (!type) return sdef; pname = Getattr(node,"name"); tm = Swig_typemap_search(op,type,pname,&mtype); - if (!tm) return 0; + if (!tm) return sdef; s = Getattr(tm,"code"); - if (!s) return 0; + if (!s) return sdef; /* Empty typemap. No match */ - if (Cmp(s,"pass") == 0) return 0; + if (Cmp(s,"pass") == 0) return sdef; s = Copy(s); /* Make a local copy of the typemap code */ @@ -1216,6 +1223,12 @@ String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const Stri if (cname) Delete(cname); if (clname) Delete(clname); if (mtype) Delete(mtype); + if (sdef) { /* put 'ref' and 'newfree' codes together */ + String *p = NewStringf("%s\n%s", sdef, s); + Delete(s); + Delete(sdef); + s = p; + } return s; }