Improve director unwrap detection for the return type
Resolve the return type to correctly determine if the type is a pointer or reference to a director class. SwigType_refptr_count_return() recently added as a simpler fix is no longer needed. The conventional approach of using the "type" rather than "decl" to analyse the return type is used instead too. Issue #1823
This commit is contained in:
parent
4a397869a2
commit
2f55379687
10 changed files with 76 additions and 90 deletions
|
|
@ -233,3 +233,38 @@ void Swig_director_parms_fixup(ParmList *parms) {
|
|||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_director_can_unwrap()
|
||||
*
|
||||
* Determine whether a function's return type can be returned as an existing
|
||||
* target language object instead of creating a new target language object.
|
||||
* Must be a director class and only for return by pointer or reference only
|
||||
* (not by value or by pointer to pointer etc).
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
bool Swig_director_can_unwrap(Node *n) {
|
||||
|
||||
// FIXME: this will not try to unwrap directors returned as non-director
|
||||
// base class pointers!
|
||||
|
||||
bool unwrap = false;
|
||||
|
||||
String *type = Getattr(n, "type");
|
||||
SwigType *t = SwigType_typedef_resolve_all(type);
|
||||
SwigType *t1 = SwigType_strip_qualifiers(t);
|
||||
SwigType *prefix = SwigType_prefix(t1);
|
||||
|
||||
if (Strcmp(prefix, "p.") == 0 || Strcmp(prefix, "r.") == 0) {
|
||||
Node *parent = Swig_methodclass(n);
|
||||
Node *module = Getattr(parent, "module");
|
||||
Node *target = Swig_directormap(module, t1);
|
||||
if (target)
|
||||
unwrap = true;
|
||||
}
|
||||
|
||||
Delete(prefix);
|
||||
Delete(t1);
|
||||
Delete(t);
|
||||
|
||||
return unwrap;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3150,25 +3150,9 @@ public:
|
|||
Replaceall(tm, "$owner", "0");
|
||||
}
|
||||
}
|
||||
// FIXME: this will not try to unwrap directors returned as non-director
|
||||
// base class pointers!
|
||||
|
||||
/* New addition to unwrap director return values so that the original
|
||||
* python object is returned instead.
|
||||
*/
|
||||
#if 1
|
||||
int unwrap = 0;
|
||||
String *decl = Getattr(n, "decl");
|
||||
if (SwigType_refptr_count_return(decl) == 1) {
|
||||
String *type = Getattr(n, "type");
|
||||
//Node *classNode = Swig_methodclass(n);
|
||||
//Node *module = Getattr(classNode, "module");
|
||||
Node *module = Getattr(parent, "module");
|
||||
Node *target = Swig_directormap(module, type);
|
||||
if (target)
|
||||
unwrap = 1;
|
||||
}
|
||||
if (unwrap) {
|
||||
// Unwrap return values that are director classes so that the original Python object is returned instead.
|
||||
if (!constructor && Swig_director_can_unwrap(n)) {
|
||||
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
||||
Printf(f->code, "director = SWIG_DIRECTOR_CAST(%s);\n", Swig_cresult_name());
|
||||
Append(f->code, "if (director) {\n");
|
||||
|
|
@ -3180,9 +3164,7 @@ public:
|
|||
} else {
|
||||
Printf(f->code, "%s\n", tm);
|
||||
}
|
||||
#else
|
||||
Printf(f->code, "%s\n", tm);
|
||||
#endif
|
||||
|
||||
Delete(tm);
|
||||
} else {
|
||||
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
|
||||
|
|
|
|||
|
|
@ -1871,24 +1871,8 @@ public:
|
|||
else
|
||||
Replaceall(tm, "$owner", "0");
|
||||
|
||||
#if 1
|
||||
// FIXME: this will not try to unwrap directors returned as non-director
|
||||
// base class pointers!
|
||||
|
||||
/* New addition to unwrap director return values so that the original
|
||||
* Ruby object is returned instead.
|
||||
*/
|
||||
bool unwrap = false;
|
||||
String *decl = Getattr(n, "decl");
|
||||
if (SwigType_refptr_count_return(decl) == 1) {
|
||||
String *type = Getattr(n, "type");
|
||||
Node *parent = Swig_methodclass(n);
|
||||
Node *modname = Getattr(parent, "module");
|
||||
Node *target = Swig_directormap(modname, type);
|
||||
if (target)
|
||||
unwrap = true;
|
||||
}
|
||||
if (unwrap) {
|
||||
// Unwrap return values that are director classes so that the original Ruby object is returned instead.
|
||||
if (Swig_director_can_unwrap(n)) {
|
||||
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
||||
Printf(f->code, "director = dynamic_cast<Swig::Director *>(%s);\n", Swig_cresult_name());
|
||||
Printf(f->code, "if (director) {\n");
|
||||
|
|
@ -1900,9 +1884,7 @@ public:
|
|||
} else {
|
||||
Printf(f->code, "%s\n", tm);
|
||||
}
|
||||
#else
|
||||
Printf(f->code, "%s\n", tm);
|
||||
#endif
|
||||
|
||||
Delete(tm);
|
||||
} else {
|
||||
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0));
|
||||
|
|
|
|||
|
|
@ -405,6 +405,7 @@ String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_Strin
|
|||
String *Swig_director_declaration(Node *n);
|
||||
void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
|
||||
void Swig_director_parms_fixup(ParmList *parms);
|
||||
bool Swig_director_can_unwrap(Node *n);
|
||||
/* directors.cxx end */
|
||||
|
||||
/* Utilities */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue