- explicitcall feature removed.

- Instead of using the swig_up flag in each director method (Python, Ruby, Ocaml) to indicate
whether the explicit C++ call to the appropriate base class method or a normal
polymorphic C++ call should be made, the new approach makes one of these calls
directly from the wrapper method.
- Java/C# recursive director method calls fixed (no need for explicitcall feature to solve this now)


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@9275 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2006-09-13 20:55:24 +00:00
commit f0d1d772fa
12 changed files with 355 additions and 303 deletions

View file

@ -1859,6 +1859,9 @@ class CSHARP : public Language {
// Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
if (Getattr(n, "overload:ignore")) return;
// Don't generate proxy method for additional explicitcall method used in directors
if (GetFlag(n, "explicitcall")) return;
if (l) {
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
l = nextSibling(l);
@ -1993,6 +1996,28 @@ class CSHARP : public Language {
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
// For director methods: generate code to selectively make a normal polymorphic call or
// an explicit method call - needed to prevent infinite recursion calls in director methods.
Node *explicit_n = Getattr(n,"explicitcallnode");
if (explicit_n) {
String *ex_overloaded_name = getOverloadedName(explicit_n);
String *ex_intermediary_function_name = Swig_name_member(proxy_class_name, ex_overloaded_name);
String *ex_imcall = Copy(imcall);
Replaceall(ex_imcall, intermediary_function_name, ex_intermediary_function_name);
String *excode = NewString("");
if (!Cmp(return_type, "void"))
Printf(excode, "if (this.GetType() == typeof(%s)) %s; else %s", proxy_class_name, imcall, ex_imcall);
else
Printf(excode, "((this.GetType() == typeof(%s)) ? %s : %s)", proxy_class_name, imcall, ex_imcall);
Clear(imcall);
Printv(imcall, excode, NIL);
Delete(ex_overloaded_name);
Delete(excode);
}
Replaceall(tm, "$imcall", imcall);
excodeSubstitute(n, tm, "csout", n);
} else {
@ -3364,6 +3389,22 @@ class CSHARP : public Language {
Printf(w->code, "}");
// We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
String *inline_extra_method = NewString("");
if (dirprot_mode() && !is_public(n) && !pure_virtual)
{
Printv(inline_extra_method, declaration, NIL);
String *extra_method_name = NewStringf("%sSwigPublic", name);
Replaceall(inline_extra_method, name, extra_method_name);
Replaceall(inline_extra_method, ";\n", " {\n ");
if (!is_void)
Printf(inline_extra_method, "return ");
String *methodcall = Swig_method_call(super, l);
Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
Delete(methodcall);
Delete(extra_method_name);
}
/* emit code */
if (status == SWIG_OK && output_director) {
if(!is_void) {
@ -3375,6 +3416,7 @@ class CSHARP : public Language {
if (!Getattr(n,"defaultargs")) {
Wrapper_print(w, f_directors);
Printv(f_directors_h, declaration, NIL);
Printv(f_directors_h, inline_extra_method, NIL);
}
}
@ -3621,6 +3663,14 @@ class CSHARP : public Language {
return SWIG_OK;
}
/* -----------------------------------------------------------------------------
* extraDirectorProtectedCPPMethodsRequired()
* ----------------------------------------------------------------------------- */
bool extraDirectorProtectedCPPMethodsRequired() const {
return false;
}
/* --------------------------------------------------------------------
* Java_director_declaration()
*

View file

@ -394,26 +394,15 @@ void emit_action(Node *n, Wrapper *f) {
action = Getattr(n,"wrap:action");
assert(action != 0);
if (!(is_public(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 */
if (!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) {
/* In order to call protected virtual director methods from the target language, we need
* to add an extra dynamic_cast to call the public C++ wrapper in the director class. */
Node* parent = Getattr(n,"parentNode");
String* symname = Getattr(parent, "sym:name");
String* dirname = NewStringf("SwigDirector_%s", symname);
String* dirdecl = NewStringf("%s *darg = 0", dirname);
Wrapper_add_local(f, "darg", dirdecl);
Printf(f->code, "darg = dynamic_cast<%s *>(arg1);\n",dirname);
Replace(action, "arg1", "darg", DOH_REPLACE_FIRST);
if (Getattr(n,"qualifier")) {
/* fix constant casting introduced by a const method decl */
String* classtype = Getattr(parent, "classtype");
/*
String *ccast = NewStringf("((%s const *)darg)",classtype);
if (Strstr(action,ccast) != 0)
*/
Replace(action, classtype, dirname, DOH_REPLACE_FIRST);
}
Delete(dirname);
Delete(dirdecl);
}

View file

@ -1870,6 +1870,9 @@ class JAVA : public Language {
// Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
if (Getattr(n, "overload:ignore")) return;
// Don't generate proxy method for additional explicitcall method used in directors
if (GetFlag(n, "explicitcall")) return;
if (l) {
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
l = nextSibling(l);
@ -1985,6 +1988,29 @@ class JAVA : public Language {
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
// For director methods: generate code to selectively make a normal polymorphic call or
// an explicit method call - needed to prevent infinite recursion calls in director methods.
Node *explicit_n = Getattr(n,"explicitcallnode");
if (explicit_n) {
String *ex_overloaded_name = getOverloadedName(explicit_n);
String *ex_intermediary_function_name = Swig_name_member(proxy_class_name, ex_overloaded_name);
String *ex_imcall = Copy(imcall);
Replaceall(ex_imcall, intermediary_function_name, ex_intermediary_function_name);
String *excode = NewString("");
if (!Cmp(return_type, "void"))
Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall);
else
Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall);
Clear(imcall);
Printv(imcall, excode, NIL);
Delete(ex_overloaded_name);
Delete(excode);
}
Replaceall(tm, "$jnicall", imcall);
} else {
Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number,
@ -3464,6 +3490,22 @@ class JAVA : public Language {
Printf(w->code, "}");
// We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
String *inline_extra_method = NewString("");
if (dirprot_mode() && !is_public(n) && !pure_virtual)
{
Printv(inline_extra_method, declaration, NIL);
String *extra_method_name = NewStringf("%sSwigPublic", name);
Replaceall(inline_extra_method, name, extra_method_name);
Replaceall(inline_extra_method, ";\n", " {\n ");
if (!is_void)
Printf(inline_extra_method, "return ");
String *methodcall = Swig_method_call(super, l);
Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
Delete(methodcall);
Delete(extra_method_name);
}
/* emit code */
if (status == SWIG_OK && output_director) {
if(!is_void) {
@ -3475,9 +3517,11 @@ class JAVA : public Language {
if (!Getattr(n,"defaultargs")) {
Wrapper_print(w, f_directors);
Printv(f_directors_h, declaration, NIL);
Printv(f_directors_h, inline_extra_method, NIL);
}
}
Delete(inline_extra_method);
Delete(qualified_return);
Delete(jnidesc);
Delete(c_ret_type);
@ -3767,6 +3811,14 @@ class JAVA : public Language {
return SWIG_OK;
}
/* -----------------------------------------------------------------------------
* extraDirectorProtectedCPPMethodsRequired()
* ----------------------------------------------------------------------------- */
bool extraDirectorProtectedCPPMethodsRequired() const {
return false;
}
/* --------------------------------------------------------------------
* Java_director_declaration()
*

View file

@ -45,6 +45,7 @@ static int InClass = 0; /* Parsing C++ or not */
static String *ClassName = 0; /* This is the real name of the current class */
static String *ClassPrefix = 0; /* Class prefix */
static String *ClassType = 0; /* Fully qualified type name to use */
static String *DirectorClassName = 0;/* Director name of the current class */
int Abstract = 0;
int ImportMode = 0;
int IsVirtual = 0;
@ -974,26 +975,27 @@ Language::functionHandler(Node *n) {
globalfunctionHandler(n);
} else {
Node* explicit_n = 0;
if (GetFlag(n, "feature:explicitcall")) {
// Add in an explicit wrapper call to virtual methods
if (Cmp(storage, "virtual") == 0 && (cplus_mode == PUBLIC))
explicit_n = Copy(n);
if (directorsEnabled() && is_member_director(CurrentClass,n) && !Extend && !extraDirectorProtectedCPPMethodsRequired()) {
bool virtual_but_not_pure_virtual = (!(Cmp(storage, "virtual")) && (Cmp(Getattr(n, "value"), "0") != 0));
if (virtual_but_not_pure_virtual) {
// Add additional wrapper which makes an explicit call to the virtual method (ie not a virtual call)
explicit_n = Copy(n);
String *new_symname = Copy(Getattr(n,"sym:name"));
String *suffix = Getattr(parentNode(n),"sym:name");
Printv(new_symname, "SwigExplicit", suffix, NIL);
Setattr(explicit_n,"sym:name", new_symname);
Delattr(explicit_n,"storage");
Delattr(explicit_n,"override");
Delattr(explicit_n,"hides");
SetFlag(explicit_n,"explicitcall");
Setattr(n, "explicitcallnode", explicit_n);
}
}
memberfunctionHandler(n);
if (explicit_n) {
String *new_symname = Copy(Getattr(n,"sym:name"));
String *suffix = Getattr(n,"feature:explicitcall:suffix");
if (!suffix)
suffix = Getattr(parentNode(n),"sym:name");
Printv(new_symname, suffix, NIL);
Setattr(explicit_n,"sym:name", new_symname);
Delattr(explicit_n,"storage");
Delattr(explicit_n,"override");
Delattr(explicit_n,"hides");
SetFlag(explicit_n,"explicitcall");
memberfunctionHandler(explicit_n);
memberfunctionHandler(explicit_n);
Delattr(explicit_n,"explicitcall");
Delete(explicit_n);
}
@ -1149,12 +1151,31 @@ Language::memberfunctionHandler(Node *n) {
Setattr(n,"classname",Getattr(CurrentClass,"allocate:smartpointerbase"));
}
}
/* Transformation */
Swig_MethodToFunction(n,ClassType, Getattr(n,"template") ? 0 : Extend | SmartPointer);
// Set up the type for the cast to this class for use when wrapping const director (virtual) methods.
// Note: protected director methods only.
String* director_type = 0;
if (!is_public(n) && (is_member_director(CurrentClass,n) || GetFlag(n, "explicitcall"))) {
director_type = Copy(DirectorClassName);
String *qualifier = Getattr(n,k_qualifier);
if (qualifier)
SwigType_push(director_type,qualifier);
SwigType_add_pointer(director_type);
}
int DirectorExtraCall = 0;
if (directorsEnabled() && is_member_director(CurrentClass,n) && !SmartPointer)
if (extraDirectorProtectedCPPMethodsRequired())
DirectorExtraCall = CWRAP_DIRECTOR_TWO_CALLS;
if (GetFlag(n, "explicitcall"))
DirectorExtraCall = CWRAP_DIRECTOR_ONE_CALL;
Swig_MethodToFunction(n, ClassType, Getattr(n,"template") ? 0 : Extend | SmartPointer | DirectorExtraCall, director_type, is_member_director(CurrentClass,n));
Setattr(n,"sym:name",fname);
functionWrapper(n);
/* DelWrapper(w);*/
Delete(director_type);
Delete(fname);
Swig_restore(n);
return SWIG_OK;
@ -1970,15 +1991,13 @@ int Language::classDirectorDestructor(Node *n) {
*/
File *f_directors = Swig_filebyname("director");
File *f_directors_h = Swig_filebyname("director_h");
String *classname= Swig_class_name(getCurrentClass());
if (Getattr(n,"throw")) {
Printf(f_directors_h, " virtual ~SwigDirector_%s() throw ();\n", classname);
Printf(f_directors, "SwigDirector_%s::~SwigDirector_%s() throw () {\n}\n\n", classname, classname);
Printf(f_directors_h, " virtual ~%s() throw ();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() throw () {\n}\n\n", DirectorClassName, DirectorClassName);
} else {
Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname);
Printf(f_directors, "SwigDirector_%s::~SwigDirector_%s() {\n}\n\n", classname, classname);
Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
Printf(f_directors, "%s::~%s() {\n}\n\n", DirectorClassName, DirectorClassName);
}
Delete(classname);
return SWIG_OK;
}
@ -2290,6 +2309,7 @@ int Language::classDeclaration(Node *n) {
}
if (dir) {
DirectorClassName = NewStringf("SwigDirector_%s", symname);
classDirector(n);
}
/* check for abstract after resolving directors */
@ -2306,6 +2326,7 @@ int Language::classDeclaration(Node *n) {
Delete(ClassType); ClassType = 0;
Delete(ClassPrefix); ClassPrefix = 0;
Delete(ClassName); ClassName = 0;
Delete(DirectorClassName); DirectorClassName = 0;
Swig_restore(n);
return SWIG_OK;
}
@ -2340,6 +2361,35 @@ int Language::classHandler(Node *n) {
/* emit director disown method */
if (hasDirector) {
classDirectorDisown(n);
/* Emit additional protected virtual methods - only needed if the language module
* codes logic in the C++ layer instead of the director proxy class method - primarily
* to catch public use of protected methods by the sripting languages. */
if (dirprot_mode() && extraDirectorProtectedCPPMethodsRequired()) {
Node *vtable = Getattr(n, "vtable");
String* symname = Getattr(n, "sym:name");
Node *item;
Iterator k;
AccessMode old_mode = cplus_mode;
cplus_mode = PROTECTED;
for (k = First(vtable); k.key; k = Next(k)) {
item = k.item;
Node *method = Getattr(item, "methodNode");
SwigType *type = Getattr(method,"nodeType");
if (Strcmp(type,"cdecl") !=0 ) continue;
String* methodname = Getattr(method,"sym:name");
String* wrapname = NewStringf("%s_%s", symname,methodname);
if (!Getattr(symbols,wrapname) && (!is_public(method))) {
Node* m = Copy(method);
Setattr(m, "director", "1");
Setattr(m,"parentNode", n);
cDeclaration(m);
Delete(m);
}
Delete(wrapname);
}
cplus_mode = old_mode;
}
}
return SWIG_OK;
@ -3049,7 +3099,7 @@ int Language::need_nonpublic_member(Node *n)
needed. */
return 1;
} else {
/* if the method is pure virtual, we needed it. */
/* if the method is pure virtual, we need it. */
int pure_virtual = (Cmp(Getattr(n,"value"),"0") == 0);
return pure_virtual;
}
@ -3067,6 +3117,14 @@ int Language::is_smart_pointer() const {
return SmartPointer;
}
/* -----------------------------------------------------------------------------
* Language::extraDirectorProtectedCPPMethodsRequired()
* ----------------------------------------------------------------------------- */
bool Language::extraDirectorProtectedCPPMethodsRequired() const {
return true;
}
/* -----------------------------------------------------------------------------
* Language::is_wrapping_class()
* ----------------------------------------------------------------------------- */

View file

@ -448,6 +448,7 @@ public:
SwigType *d = Getattr(n,"type");
String *return_type_normalized = normalizeTemplatedClassName(d);
ParmList *l = Getattr(n,"parms");
int director_method = 0;
Parm *p;
Wrapper *f = NewWrapper();
@ -465,10 +466,7 @@ public:
int numreq;
int newobj = GetFlag(n,"feature:new");
String *nodeType = Getattr(n, "nodeType");
int constructor = !Cmp(nodeType, "constructor");
int destructor = (!Cmp(nodeType, "destructor"));
String *storage = Getattr(n,"storage");
int isVirtual = !Cmp(storage,"virtual");
String *overname = 0;
bool isOverloaded = Getattr(n,"sym:overloaded") ? true : false;
@ -687,18 +685,12 @@ public:
// (the smart-pointer) and the director object (the "pointee") are
// distinct.
if (directorsEnabled()) {
if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && !destructor
&& isVirtual && !Getattr(n,"feature:nodirector")) {
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
Printf(f->code,
"if (director && !director->swig_get_up(false))"
"director->swig_set_up();\n");
}
}
director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
if (director_method) {
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
Wrapper_add_local(f, "upcall", "bool upcall = false");
Append(f->code, "upcall = (director);\n");
}
// Now write code to make the function call
@ -1665,17 +1657,6 @@ public:
Printv(w->code, "swig_result = Val_unit;\n",0);
Printf(w->code,"args = Val_unit;\n");
/* direct call to superclass if _up is set */
if( pure_virtual ) {
Printf(w->code, "if (swig_get_up()) {\n");
Printf(w->code, " throw Swig::DirectorPureVirtualException();\n");
Printf(w->code, "}\n");
} else {
Printf(w->code, "if (swig_get_up()) {\n");
Printf(w->code, "CAMLreturn(%s);\n", Swig_method_call(super,l));
Printf(w->code, "}\n");
}
/* wrap complex arguments to values */
Printv(w->code, wrap_args, NIL);
@ -1778,11 +1759,28 @@ public:
Printf(w->code, "}\n");
// We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
String *inline_extra_method = NewString("");
if (dirprot_mode() && !is_public(n) && !pure_virtual)
{
Printv(inline_extra_method, declaration, NIL);
String *extra_method_name = NewStringf("%sSwigPublic", name);
Replaceall(inline_extra_method, name, extra_method_name);
Replaceall(inline_extra_method, ";\n", " {\n ");
if (!is_void)
Printf(inline_extra_method, "return ");
String *methodcall = Swig_method_call(super, l);
Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
Delete(methodcall);
Delete(extra_method_name);
}
/* emit the director method */
if (status == SWIG_OK) {
if (!Getattr(n,"defaultargs")) {
Wrapper_print(w, f_directors);
Printv(f_directors_h, declaration, NIL);
Printv(f_directors_h, inline_extra_method, NIL);
}
}

View file

@ -1612,7 +1612,6 @@ public:
int constructor = (!Cmp(nodeType, "constructor"));
int destructor = (!Cmp(nodeType, "destructor"));
String *storage = Getattr(n,"storage");
int isVirtual = (Cmp(storage,"virtual") == 0);
/* Only the first constructor is handled as init method. Others
constructor can be emitted via %rename */
int handled_as_init = 0;
@ -1946,25 +1945,21 @@ public:
// (the smart-pointer) and the director object (the "pointee") are
// distinct.
if (directorsEnabled()) {
if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && !destructor
&& isVirtual && !Getattr(n,"feature:nodirector")) {
director_method = 1;
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
if (dirprot_mode() && !is_public(n)) {
Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
Printf(f->code, "SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
Append(f->code, "SWIG_fail;\n");
Append(f->code, "}\n");
}
if (funpack) {
Append(f->code, "if (director && (director->swig_get_self()==swig_obj[0])) director->swig_set_up();\n");
} else {
Append(f->code, "if (director && (director->swig_get_self()==obj0)) director->swig_set_up();\n");
}
}
director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
if (director_method) {
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
if (dirprot_mode() && !is_public(n)) {
Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
Printf(f->code, "SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
Append(f->code, "SWIG_fail;\n");
Append(f->code, "}\n");
}
Wrapper_add_local(f, "upcall", "bool upcall = false");
if (funpack) {
Append(f->code, "upcall = (director && (director->swig_get_self()==swig_obj[0]));\n");
} else {
Append(f->code, "upcall = (director && (director->swig_get_self()==obj0));\n");
}
}
@ -3570,29 +3565,12 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
p = nextSibling(p);
}
/* add the method name as a PyString */
/* add the method name as a PyString */
String *pyname = Getattr(n,"sym:name");
int allow_thread = threads_enable(n);
/* direct call to superclass if _up is set */
if (allow_thread) thread_begin_block(n, w->code);
Append(w->code, "if (swig_get_up()) {\n");
if (pure_virtual) {
Printf(w->code,
"Swig::DirectorPureVirtualException::raise(\"%s.\");\n",Swig_method_call(super,l));
} else {
if (allow_thread) thread_begin_allow(n, w->code);
if (is_void) {
Printf(w->code, "%s;\n", Swig_method_call(super,l));
Append(w->code, "return;\n");
} else {
Printf(w->code, "return %s;\n", Swig_method_call(super,l));
}
if (allow_thread) thread_end_allow(n, w->code);
}
Append(w->code, "}\n");
/* declare method return value
* if the return value is a reference or const reference, a specialized typemap must
@ -3784,11 +3762,28 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
}
Append(w->code, "}\n");
// We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
String *inline_extra_method = NewString("");
if (dirprot_mode() && !is_public(n) && !pure_virtual)
{
Printv(inline_extra_method, declaration, NIL);
String *extra_method_name = NewStringf("%sSwigPublic", name);
Replaceall(inline_extra_method, name, extra_method_name);
Replaceall(inline_extra_method, ";\n", " {\n ");
if (!is_void)
Printf(inline_extra_method, "return ");
String *methodcall = Swig_method_call(super, l);
Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
Delete(methodcall);
Delete(extra_method_name);
}
/* emit the director method */
if (status == SWIG_OK) {
if (!Getattr(n,"defaultargs")) {
Wrapper_print(w, f_directors);
Printv(f_directors_h, declaration, NIL);
Printv(f_directors_h, inline_extra_method, NIL);
}
}

View file

@ -991,7 +991,6 @@ public:
bool constructor;
bool destructor;
String *storage;
bool isVirtual;
String *symname = Copy(Getattr(n,"sym:name"));
SwigType *t = Getattr(n,"type");
@ -1009,7 +1008,6 @@ public:
constructor = (!Cmp(nodeType, "constructor"));
destructor = (!Cmp(nodeType, "destructor"));
storage = Getattr(n, "storage");
isVirtual = (Cmp(storage, "virtual") == 0);
/* If the C++ class constructor is overloaded, we only want to
* write out the "new" singleton method once since it is always
@ -1135,16 +1133,12 @@ public:
// (the smart-pointer) and the director object (the "pointee") are
// distinct.
if (directorsEnabled()) {
if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && !destructor
&& isVirtual && !Getattr(n,"feature:nodirector")) {
director_method = 1;
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
Printf(f->code, "if (director && (director->swig_get_self() == self)) director->swig_set_up();\n");
}
}
director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
if (director_method) {
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
Wrapper_add_local(f, "upcall", "bool upcall = false");
Append(f->code, "upcall = (director && (director->swig_get_self() == self));\n");
}
/* Now write code to make the function call */
@ -2484,20 +2478,6 @@ public:
/* declare Ruby return value */
Wrapper_add_local(w, "result", "VALUE result");
/* direct call to superclass if _up is set */
Printf(w->code, "if (swig_get_up()) {\n");
if (pure_virtual) {
Printf(w->code, "throw Swig::DirectorPureVirtualException();\n");
} else {
if (is_void) {
Printf(w->code, "%s;\n", Swig_method_call(super,l));
Printf(w->code, "return;\n");
} else {
Printf(w->code, "return %s;\n", Swig_method_call(super,l));
}
}
Printf(w->code, "}\n");
/* wrap complex arguments to VALUEs */
Printv(w->code, wrap_args, NIL);
@ -2588,14 +2568,30 @@ public:
}
Delete(rettype);
}
Printf(w->code, "}\n");
// We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
String *inline_extra_method = NewString("");
if (dirprot_mode() && !is_public(n) && !pure_virtual)
{
Printv(inline_extra_method, declaration, NIL);
String *extra_method_name = NewStringf("%sSwigPublic", name);
Replaceall(inline_extra_method, name, extra_method_name);
Replaceall(inline_extra_method, ";\n", " {\n ");
if (!is_void)
Printf(inline_extra_method, "return ");
String *methodcall = Swig_method_call(super, l);
Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
Delete(methodcall);
Delete(extra_method_name);
}
/* emit the director method */
if (status == SWIG_OK) {
if (!Getattr(n,"defaultargs")) {
Wrapper_print(w, f_directors);
Printv(f_directors_h, declaration, NIL);
Printv(f_directors_h, inline_extra_method, NIL);
}
}

View file

@ -272,6 +272,9 @@ protected:
/* Return true if the current method is part of a smart-pointer */
int is_smart_pointer() const;
/* Some language modules require additional wrappers for virtual methods not declared in sub-classes */
virtual bool extraDirectorProtectedCPPMethodsRequired() const;
/* Director subclass comparison test */
String *none_comparison;

View file

@ -382,7 +382,7 @@ Swig_cfunction_call(String_or_char *name, ParmList *parms) {
* ----------------------------------------------------------------------------- */
static String *
Swig_cmethod_call(String_or_char *name, ParmList *parms, String_or_char *self, String *explicit_qualifier) {
Swig_cmethod_call(String_or_char *name, ParmList *parms, String_or_char *self, String *explicit_qualifier, SwigType *director_type) {
String *func, *nname;
int i = 0;
Parm *p = parms;
@ -402,36 +402,44 @@ Swig_cmethod_call(String_or_char *name, ParmList *parms, String_or_char *self, S
} else {
nname = SwigType_namestr(name);
}
pt = Getattr(p,k_type);
/* If the method is invoked through a dereferenced pointer, we don't add any casts
(needed for smart pointers). Otherwise, we cast to the appropriate type */
if (Strstr(func,"*this")) {
String *pname = Swig_cparm_name(p,0);
Replaceall(func,"this", pname);
Delete(pname);
} else {
String *pname = Swig_cparm_name(p,0);
String *rcaststr = SwigType_rcaststr(pt, pname);
if (director_type) {
const char *pname = "darg";
String *rcaststr = SwigType_rcaststr(director_type, pname);
Replaceall(func,"this", rcaststr);
Delete(rcaststr);
Delete(pname);
} else {
pt = Getattr(p,k_type);
/* If the method is invoked through a dereferenced pointer, we don't add any casts
(needed for smart pointers). Otherwise, we cast to the appropriate type */
if (Strstr(func,"*this")) {
String *pname = Swig_cparm_name(p,0);
Replaceall(func,"this", pname);
Delete(pname);
} else {
String *pname = Swig_cparm_name(p,0);
String *rcaststr = SwigType_rcaststr(pt, pname);
Replaceall(func,"this", rcaststr);
Delete(rcaststr);
Delete(pname);
}
/*
SWIGTEMPLATEDESIMBUAGATOR is compiler dependent (swiglabels.swg),
- SUN Studio 9 requires 'template',
- gcc-3.4 forbids the use of 'template' (correctly implementing the ISO C++ standard)
the others don't seem to care,
*/
if (SwigType_istemplate(name))
Printf(func,"SWIGTEMPLATEDISAMBIGUATOR ");
if (explicit_qualifier) {
Printv(func, explicit_qualifier, "::", NIL);
}
}
/*
SWIGTEMPLATEDESIMBUAGATOR is compiler dependent (swiglabels.swg),
- SUN Studio 9 requires 'template',
- gcc-3.4 forbids the use of 'template'.
the rest seems not caring very much,
*/
if (SwigType_istemplate(name))
Printf(func,"SWIGTEMPLATEDISAMBIGUATOR ");
if (explicit_qualifier)
Printv(func, explicit_qualifier, "::", NIL);
Printf(func,"%s(", nname);
i++;
@ -787,7 +795,7 @@ Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms,
* ----------------------------------------------------------------------------- */
int
Swig_MethodToFunction(Node *n, String *classname, int flags) {
Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *director_type, int is_director) {
String *name, *qualifier;
ParmList *parms;
SwigType *type;
@ -845,13 +853,51 @@ Swig_MethodToFunction(Node *n, String *classname, int flags) {
/* Generate action code for the access */
if (!(flags & CWRAP_EXTEND)) {
/* Call the explicit method rather than allow for a polymorphic call */
String *explicit_qualifier = GetFlag(n,"explicitcall") ?
SwigType_namestr(Getattr(Getattr(parentNode(n),"typescope"),k_qname)) : 0;
String *explicit_qualifier = 0;
String *call = 0;
String *cres = 0;
String *explicitcall_name = 0;
int pure_virtual = !(Cmp(Getattr(n,k_storage), "virtual")) && !(Cmp(Getattr(n,k_value), "0"));
String *call = Swig_cmethod_call(name,p,self,explicit_qualifier);
String *cres = Swig_cresult(Getattr(n,k_type),k_result, call);
Setattr(n,k_wrapaction, cres);
/* Call the explicit method rather than allow for a polymorphic call */
if ((flags & CWRAP_DIRECTOR_TWO_CALLS) || (flags & CWRAP_DIRECTOR_ONE_CALL)) {
String* access = Getattr(n, "access");
if (access && (Cmp(access, "protected") == 0)) {
/* If protected access (can only be if a director method) then call the extra public accessor method (language module must provide this) */
String *explicit_qualifier_tmp = SwigType_namestr(Getattr(Getattr(parentNode(n),"typescope"),k_qname));
explicitcall_name = NewStringf("%sSwigPublic", name);
explicit_qualifier = NewStringf("SwigDirector_%s", explicit_qualifier_tmp);
Delete(explicit_qualifier_tmp);
} else {
explicit_qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n),"typescope"),k_qname));
}
}
call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type);
cres = Swig_cresult(Getattr(n,k_type),k_result, call);
if (pure_virtual && is_director && (flags & CWRAP_DIRECTOR_TWO_CALLS)) {
String *qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n),"typescope"),k_qname));
Delete(cres);
cres = NewStringf("Swig::DirectorPureVirtualException::raise(\"%s::%s\");", qualifier, name);
Delete(qualifier);
}
if (flags & CWRAP_DIRECTOR_TWO_CALLS) {
/* Create two method calls, one to call the explicit method, the other a normal polymorphic function call */
String *cres_both_calls = NewStringf("");
String *call_extra = Swig_cmethod_call(name, p, self, 0, director_type);
String *cres_extra = Swig_cresult(Getattr(n,k_type),k_result, call_extra);
Printv(cres_both_calls, "if (upcall) {\n", cres, "\n", "} else {", cres_extra, "\n}", NIL);
Setattr(n,k_wrapaction, cres_both_calls);
Delete(cres_extra);
Delete(call_extra);
Delete(cres_both_calls);
} else {
Setattr(n,k_wrapaction, cres);
}
Delete(explicitcall_name);
Delete(call);
Delete(cres);
Delete(explicit_qualifier);

View file

@ -494,7 +494,7 @@ extern int Swig_add_extension_code(Node *n, const String *function_name,
/* --- Transformations --- */
extern int Swig_MethodToFunction(Node *n, String *classname, int flags);
extern int Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *director_type, int is_director);
extern int Swig_ConstructorToFunction(Node *n, String *classname,
String *none_comparison,
String *director_ctor,
@ -508,6 +508,8 @@ extern int Swig_VarsetToFunction(Node *n, int flags);
#define CWRAP_EXTEND 0x01
#define CWRAP_SMART_POINTER 0x02
#define CWRAP_NATURAL_VAR 0x04
#define CWRAP_DIRECTOR_ONE_CALL 0x08
#define CWRAP_DIRECTOR_TWO_CALLS 0x10
/* --- Director Helpers --- */
extern Node *Swig_methodclass(Node *n);