- 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:
parent
a19cc4444e
commit
f0d1d772fa
12 changed files with 355 additions and 303 deletions
|
|
@ -83,7 +83,6 @@
|
||||||
<li><a href="#java_directors_classes">Director classes</a>
|
<li><a href="#java_directors_classes">Director classes</a>
|
||||||
<li><a href="#java_directors_overhead">Overhead and code bloat</a>
|
<li><a href="#java_directors_overhead">Overhead and code bloat</a>
|
||||||
<li><a href="#java_directors_example">Simple directors example</a>
|
<li><a href="#java_directors_example">Simple directors example</a>
|
||||||
<li><a href="#java_directors_explicitcall">Director base method calls</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#common_customization">Common customization features</a>
|
<li><a href="#common_customization">Common customization features</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -3204,62 +3203,6 @@ directorDerived::upcall_method() invoked.
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<H3><a name="java_directors_explicitcall"></a>20.5.5 Director base method calls</H3>
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
There is a limitation with Java directors when calling a base class method from an overridden method.
|
|
||||||
A <tt>java.lang.StackOverflowError</tt> exception will be thrown as the code makes recursive calls from the C++ layer
|
|
||||||
to the Java layer and back again in the same method. The <a href="SWIGPlus.html#SWIGPlus_explicitcall">explicitcall feature flag</a>
|
|
||||||
is one way to work around this problem. Consider the following C++ code:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
%feature("director");
|
|
||||||
%feature("explicitcall");
|
|
||||||
%include <std_string.i>
|
|
||||||
|
|
||||||
%inline %{
|
|
||||||
struct Thing {
|
|
||||||
virtual std::string getit() { return "Thing"; }
|
|
||||||
virtual ~Thing() {}
|
|
||||||
};
|
|
||||||
%}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
and the following Java class:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
class JavaThing extends Thing {
|
|
||||||
public String getit() {
|
|
||||||
return "Java" + super.getit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The overridden <tt>JavaThing.getit()</tt> method will throw the <tt>java.lang.StackOverflowError</tt> exception when called.
|
|
||||||
Fixing this would impose a performance penalty on all director methods and would not be able to automatically deal with pure
|
|
||||||
virtual methods for which a method body is not always defined. Instead, users are advised to use the explicitcall
|
|
||||||
feature flag which generates an additional method <tt>getitThing()</tt>. The modified version will then avoid the recursive calls:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
class JavaThing extends Thing {
|
|
||||||
public String getit() {
|
|
||||||
return "Java" + super.getitThing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<H2><a name="common_customization"></a>20.6 Common customization features</H2>
|
<H2><a name="common_customization"></a>20.6 Common customization features</H2>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1668,86 +1668,6 @@ functions for virtual members that are already defined in a base
|
||||||
class.
|
class.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H3><a name="SWIGPlus_explicitcall"></a>6.13.1 Explicit base class method calls</H3>
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
SWIG uses standard C++ polymorphic behaviour to ensure the correct virtual method is called
|
|
||||||
when generating wrappers for virtual methods.
|
|
||||||
However, in C++ it is possible, albeit rare, to call a particular base class method in the inheritance
|
|
||||||
hierarchy. This C++ functionality is available to target languages with the
|
|
||||||
<tt>explicitcall</tt> <a href="Customization.html#Customization_feature_flags">feature flag</a> directive.
|
|
||||||
This feature only works on virtual methods and when it is specified it generates an
|
|
||||||
additional wrapper method. By default, the name of this method is the original method name mangled with
|
|
||||||
the name of the class as a suffix. However, the name of the method can be controlled by specifying a different
|
|
||||||
suffix in the <tt>suffix</tt>
|
|
||||||
<a href="Customization.html#Customization_feature_attributes">feature attribute</a>.
|
|
||||||
For example, consider the following code:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
%explicitcall; // enable explicitcall feature for all virtual methods
|
|
||||||
%feature("explicitcall", suffix="Bambino") Child::describe;
|
|
||||||
|
|
||||||
struct Person {
|
|
||||||
Person() {}
|
|
||||||
virtual const char * describe() { return "Person"; }
|
|
||||||
virtual ~Person() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Child : Person {
|
|
||||||
virtual const char * describe() { return "Child"; }
|
|
||||||
};
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
From Python, it is then possible to call explicit methods in the inheritance hierarchy.
|
|
||||||
Note the suffix names:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="targetlang">
|
|
||||||
<pre>
|
|
||||||
$ python
|
|
||||||
>>> from example import *
|
|
||||||
>>> child = Child()
|
|
||||||
>>> print child.describe() # normal polymorphic call
|
|
||||||
Child
|
|
||||||
>>> print child.describePerson() # explicit Person::describe call
|
|
||||||
Person
|
|
||||||
>>> print child.describeBambino() # explicit Child::describe call
|
|
||||||
Child
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The pseudo C++ code generated for the <tt>Person::describe</tt> methods is as follows:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
// Normal virtual method wrapper
|
|
||||||
const char * Person_talk(Person *obj) {
|
|
||||||
const char * ret = obj->describe();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additional wrapper due to %explicitcall
|
|
||||||
const char * Person_talkPerson(Person *obj) {
|
|
||||||
const char * ret = obj->Person::describe();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Please note that if this feature is enabled globally, it will apply to all virtual methods.
|
|
||||||
This includes pure virtual methods which may or may not have a body defined.
|
|
||||||
If, as is often the case, your pure virtual methods do not have a body defined you might get unresolved linker errors on some platforms.
|
|
||||||
<tt>%noexplicitcall</tt> can then be used to turn this feature off for the problem methods.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<H2><a name="SWIGPlus_nn21"></a>6.14 A brief discussion of multiple inheritance, pointers, and type checking</H2>
|
<H2><a name="SWIGPlus_nn21"></a>6.14 A brief discussion of multiple inheritance, pointers, and type checking</H2>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1859,6 +1859,9 @@ class CSHARP : public Language {
|
||||||
// Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
|
// Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
|
||||||
if (Getattr(n, "overload:ignore")) return;
|
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 (l) {
|
||||||
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
|
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
|
||||||
l = nextSibling(l);
|
l = nextSibling(l);
|
||||||
|
|
@ -1993,6 +1996,28 @@ class CSHARP : public Language {
|
||||||
else
|
else
|
||||||
Replaceall(tm,"$owner","false");
|
Replaceall(tm,"$owner","false");
|
||||||
substituteClassname(t, tm);
|
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);
|
Replaceall(tm, "$imcall", imcall);
|
||||||
excodeSubstitute(n, tm, "csout", n);
|
excodeSubstitute(n, tm, "csout", n);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3364,6 +3389,22 @@ class CSHARP : public Language {
|
||||||
|
|
||||||
Printf(w->code, "}");
|
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 */
|
/* emit code */
|
||||||
if (status == SWIG_OK && output_director) {
|
if (status == SWIG_OK && output_director) {
|
||||||
if(!is_void) {
|
if(!is_void) {
|
||||||
|
|
@ -3375,6 +3416,7 @@ class CSHARP : public Language {
|
||||||
if (!Getattr(n,"defaultargs")) {
|
if (!Getattr(n,"defaultargs")) {
|
||||||
Wrapper_print(w, f_directors);
|
Wrapper_print(w, f_directors);
|
||||||
Printv(f_directors_h, declaration, NIL);
|
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;
|
return SWIG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* extraDirectorProtectedCPPMethodsRequired()
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
bool extraDirectorProtectedCPPMethodsRequired() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* Java_director_declaration()
|
* Java_director_declaration()
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -394,26 +394,15 @@ void emit_action(Node *n, Wrapper *f) {
|
||||||
action = Getattr(n,"wrap:action");
|
action = Getattr(n,"wrap:action");
|
||||||
assert(action != 0);
|
assert(action != 0);
|
||||||
|
|
||||||
if (!(is_public(n)) && is_member_director(n)) {
|
if (!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) {
|
||||||
/* We need to add an extra dynamic_cast to
|
/* In order to call protected virtual director methods from the target language, we need
|
||||||
access the director class, where the virtual
|
* to add an extra dynamic_cast to call the public C++ wrapper in the director class. */
|
||||||
methods are all public */
|
|
||||||
Node* parent = Getattr(n,"parentNode");
|
Node* parent = Getattr(n,"parentNode");
|
||||||
String* symname = Getattr(parent, "sym:name");
|
String* symname = Getattr(parent, "sym:name");
|
||||||
String* dirname = NewStringf("SwigDirector_%s", symname);
|
String* dirname = NewStringf("SwigDirector_%s", symname);
|
||||||
String* dirdecl = NewStringf("%s *darg = 0", dirname);
|
String* dirdecl = NewStringf("%s *darg = 0", dirname);
|
||||||
Wrapper_add_local(f, "darg", dirdecl);
|
Wrapper_add_local(f, "darg", dirdecl);
|
||||||
Printf(f->code, "darg = dynamic_cast<%s *>(arg1);\n",dirname);
|
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(dirname);
|
||||||
Delete(dirdecl);
|
Delete(dirdecl);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1870,6 +1870,9 @@ class JAVA : public Language {
|
||||||
// Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
|
// Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
|
||||||
if (Getattr(n, "overload:ignore")) return;
|
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 (l) {
|
||||||
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
|
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
|
||||||
l = nextSibling(l);
|
l = nextSibling(l);
|
||||||
|
|
@ -1985,6 +1988,29 @@ class JAVA : public Language {
|
||||||
else
|
else
|
||||||
Replaceall(tm,"$owner","false");
|
Replaceall(tm,"$owner","false");
|
||||||
substituteClassname(t, tm);
|
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);
|
Replaceall(tm, "$jnicall", imcall);
|
||||||
} else {
|
} else {
|
||||||
Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number,
|
Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number,
|
||||||
|
|
@ -3464,6 +3490,22 @@ class JAVA : public Language {
|
||||||
|
|
||||||
Printf(w->code, "}");
|
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 */
|
/* emit code */
|
||||||
if (status == SWIG_OK && output_director) {
|
if (status == SWIG_OK && output_director) {
|
||||||
if(!is_void) {
|
if(!is_void) {
|
||||||
|
|
@ -3475,9 +3517,11 @@ class JAVA : public Language {
|
||||||
if (!Getattr(n,"defaultargs")) {
|
if (!Getattr(n,"defaultargs")) {
|
||||||
Wrapper_print(w, f_directors);
|
Wrapper_print(w, f_directors);
|
||||||
Printv(f_directors_h, declaration, NIL);
|
Printv(f_directors_h, declaration, NIL);
|
||||||
|
Printv(f_directors_h, inline_extra_method, NIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Delete(inline_extra_method);
|
||||||
Delete(qualified_return);
|
Delete(qualified_return);
|
||||||
Delete(jnidesc);
|
Delete(jnidesc);
|
||||||
Delete(c_ret_type);
|
Delete(c_ret_type);
|
||||||
|
|
@ -3767,6 +3811,14 @@ class JAVA : public Language {
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* extraDirectorProtectedCPPMethodsRequired()
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
bool extraDirectorProtectedCPPMethodsRequired() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* Java_director_declaration()
|
* Java_director_declaration()
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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 *ClassName = 0; /* This is the real name of the current class */
|
||||||
static String *ClassPrefix = 0; /* Class prefix */
|
static String *ClassPrefix = 0; /* Class prefix */
|
||||||
static String *ClassType = 0; /* Fully qualified type name to use */
|
static String *ClassType = 0; /* Fully qualified type name to use */
|
||||||
|
static String *DirectorClassName = 0;/* Director name of the current class */
|
||||||
int Abstract = 0;
|
int Abstract = 0;
|
||||||
int ImportMode = 0;
|
int ImportMode = 0;
|
||||||
int IsVirtual = 0;
|
int IsVirtual = 0;
|
||||||
|
|
@ -974,26 +975,27 @@ Language::functionHandler(Node *n) {
|
||||||
globalfunctionHandler(n);
|
globalfunctionHandler(n);
|
||||||
} else {
|
} else {
|
||||||
Node* explicit_n = 0;
|
Node* explicit_n = 0;
|
||||||
if (GetFlag(n, "feature:explicitcall")) {
|
if (directorsEnabled() && is_member_director(CurrentClass,n) && !Extend && !extraDirectorProtectedCPPMethodsRequired()) {
|
||||||
// Add in an explicit wrapper call to virtual methods
|
bool virtual_but_not_pure_virtual = (!(Cmp(storage, "virtual")) && (Cmp(Getattr(n, "value"), "0") != 0));
|
||||||
if (Cmp(storage, "virtual") == 0 && (cplus_mode == PUBLIC))
|
if (virtual_but_not_pure_virtual) {
|
||||||
explicit_n = Copy(n);
|
// 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);
|
memberfunctionHandler(n);
|
||||||
|
|
||||||
if (explicit_n) {
|
if (explicit_n) {
|
||||||
String *new_symname = Copy(Getattr(n,"sym:name"));
|
memberfunctionHandler(explicit_n);
|
||||||
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);
|
|
||||||
Delattr(explicit_n,"explicitcall");
|
Delattr(explicit_n,"explicitcall");
|
||||||
Delete(explicit_n);
|
Delete(explicit_n);
|
||||||
}
|
}
|
||||||
|
|
@ -1149,12 +1151,31 @@ Language::memberfunctionHandler(Node *n) {
|
||||||
Setattr(n,"classname",Getattr(CurrentClass,"allocate:smartpointerbase"));
|
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);
|
Setattr(n,"sym:name",fname);
|
||||||
functionWrapper(n);
|
functionWrapper(n);
|
||||||
|
|
||||||
/* DelWrapper(w);*/
|
Delete(director_type);
|
||||||
Delete(fname);
|
Delete(fname);
|
||||||
Swig_restore(n);
|
Swig_restore(n);
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
|
|
@ -1970,15 +1991,13 @@ int Language::classDirectorDestructor(Node *n) {
|
||||||
*/
|
*/
|
||||||
File *f_directors = Swig_filebyname("director");
|
File *f_directors = Swig_filebyname("director");
|
||||||
File *f_directors_h = Swig_filebyname("director_h");
|
File *f_directors_h = Swig_filebyname("director_h");
|
||||||
String *classname= Swig_class_name(getCurrentClass());
|
|
||||||
if (Getattr(n,"throw")) {
|
if (Getattr(n,"throw")) {
|
||||||
Printf(f_directors_h, " virtual ~SwigDirector_%s() throw ();\n", classname);
|
Printf(f_directors_h, " virtual ~%s() throw ();\n", DirectorClassName);
|
||||||
Printf(f_directors, "SwigDirector_%s::~SwigDirector_%s() throw () {\n}\n\n", classname, classname);
|
Printf(f_directors, "%s::~%s() throw () {\n}\n\n", DirectorClassName, DirectorClassName);
|
||||||
} else {
|
} else {
|
||||||
Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname);
|
Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
|
||||||
Printf(f_directors, "SwigDirector_%s::~SwigDirector_%s() {\n}\n\n", classname, classname);
|
Printf(f_directors, "%s::~%s() {\n}\n\n", DirectorClassName, DirectorClassName);
|
||||||
}
|
}
|
||||||
Delete(classname);
|
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2290,6 +2309,7 @@ int Language::classDeclaration(Node *n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir) {
|
if (dir) {
|
||||||
|
DirectorClassName = NewStringf("SwigDirector_%s", symname);
|
||||||
classDirector(n);
|
classDirector(n);
|
||||||
}
|
}
|
||||||
/* check for abstract after resolving directors */
|
/* check for abstract after resolving directors */
|
||||||
|
|
@ -2306,6 +2326,7 @@ int Language::classDeclaration(Node *n) {
|
||||||
Delete(ClassType); ClassType = 0;
|
Delete(ClassType); ClassType = 0;
|
||||||
Delete(ClassPrefix); ClassPrefix = 0;
|
Delete(ClassPrefix); ClassPrefix = 0;
|
||||||
Delete(ClassName); ClassName = 0;
|
Delete(ClassName); ClassName = 0;
|
||||||
|
Delete(DirectorClassName); DirectorClassName = 0;
|
||||||
Swig_restore(n);
|
Swig_restore(n);
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -2340,6 +2361,35 @@ int Language::classHandler(Node *n) {
|
||||||
/* emit director disown method */
|
/* emit director disown method */
|
||||||
if (hasDirector) {
|
if (hasDirector) {
|
||||||
classDirectorDisown(n);
|
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;
|
return SWIG_OK;
|
||||||
|
|
@ -3049,7 +3099,7 @@ int Language::need_nonpublic_member(Node *n)
|
||||||
needed. */
|
needed. */
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} 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);
|
int pure_virtual = (Cmp(Getattr(n,"value"),"0") == 0);
|
||||||
return pure_virtual;
|
return pure_virtual;
|
||||||
}
|
}
|
||||||
|
|
@ -3067,6 +3117,14 @@ int Language::is_smart_pointer() const {
|
||||||
return SmartPointer;
|
return SmartPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Language::extraDirectorProtectedCPPMethodsRequired()
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
bool Language::extraDirectorProtectedCPPMethodsRequired() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Language::is_wrapping_class()
|
* Language::is_wrapping_class()
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -448,6 +448,7 @@ public:
|
||||||
SwigType *d = Getattr(n,"type");
|
SwigType *d = Getattr(n,"type");
|
||||||
String *return_type_normalized = normalizeTemplatedClassName(d);
|
String *return_type_normalized = normalizeTemplatedClassName(d);
|
||||||
ParmList *l = Getattr(n,"parms");
|
ParmList *l = Getattr(n,"parms");
|
||||||
|
int director_method = 0;
|
||||||
Parm *p;
|
Parm *p;
|
||||||
|
|
||||||
Wrapper *f = NewWrapper();
|
Wrapper *f = NewWrapper();
|
||||||
|
|
@ -465,10 +466,7 @@ public:
|
||||||
int numreq;
|
int numreq;
|
||||||
int newobj = GetFlag(n,"feature:new");
|
int newobj = GetFlag(n,"feature:new");
|
||||||
String *nodeType = Getattr(n, "nodeType");
|
String *nodeType = Getattr(n, "nodeType");
|
||||||
int constructor = !Cmp(nodeType, "constructor");
|
|
||||||
int destructor = (!Cmp(nodeType, "destructor"));
|
int destructor = (!Cmp(nodeType, "destructor"));
|
||||||
String *storage = Getattr(n,"storage");
|
|
||||||
int isVirtual = !Cmp(storage,"virtual");
|
|
||||||
String *overname = 0;
|
String *overname = 0;
|
||||||
bool isOverloaded = Getattr(n,"sym:overloaded") ? true : false;
|
bool isOverloaded = Getattr(n,"sym:overloaded") ? true : false;
|
||||||
|
|
||||||
|
|
@ -687,18 +685,12 @@ public:
|
||||||
// (the smart-pointer) and the director object (the "pointee") are
|
// (the smart-pointer) and the director object (the "pointee") are
|
||||||
// distinct.
|
// distinct.
|
||||||
|
|
||||||
if (directorsEnabled()) {
|
director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
|
||||||
if (!is_smart_pointer()) {
|
if (director_method) {
|
||||||
if (/*directorbase &&*/ !constructor && !destructor
|
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
||||||
&& isVirtual && !Getattr(n,"feature:nodirector")) {
|
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
|
||||||
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
Wrapper_add_local(f, "upcall", "bool upcall = false");
|
||||||
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
|
Append(f->code, "upcall = (director);\n");
|
||||||
|
|
||||||
Printf(f->code,
|
|
||||||
"if (director && !director->swig_get_up(false))"
|
|
||||||
"director->swig_set_up();\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now write code to make the function call
|
// Now write code to make the function call
|
||||||
|
|
@ -1665,17 +1657,6 @@ public:
|
||||||
Printv(w->code, "swig_result = Val_unit;\n",0);
|
Printv(w->code, "swig_result = Val_unit;\n",0);
|
||||||
Printf(w->code,"args = Val_unit;\n");
|
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 */
|
/* wrap complex arguments to values */
|
||||||
Printv(w->code, wrap_args, NIL);
|
Printv(w->code, wrap_args, NIL);
|
||||||
|
|
||||||
|
|
@ -1778,11 +1759,28 @@ public:
|
||||||
|
|
||||||
Printf(w->code, "}\n");
|
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 */
|
/* emit the director method */
|
||||||
if (status == SWIG_OK) {
|
if (status == SWIG_OK) {
|
||||||
if (!Getattr(n,"defaultargs")) {
|
if (!Getattr(n,"defaultargs")) {
|
||||||
Wrapper_print(w, f_directors);
|
Wrapper_print(w, f_directors);
|
||||||
Printv(f_directors_h, declaration, NIL);
|
Printv(f_directors_h, declaration, NIL);
|
||||||
|
Printv(f_directors_h, inline_extra_method, NIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1612,7 +1612,6 @@ public:
|
||||||
int constructor = (!Cmp(nodeType, "constructor"));
|
int constructor = (!Cmp(nodeType, "constructor"));
|
||||||
int destructor = (!Cmp(nodeType, "destructor"));
|
int destructor = (!Cmp(nodeType, "destructor"));
|
||||||
String *storage = Getattr(n,"storage");
|
String *storage = Getattr(n,"storage");
|
||||||
int isVirtual = (Cmp(storage,"virtual") == 0);
|
|
||||||
/* Only the first constructor is handled as init method. Others
|
/* Only the first constructor is handled as init method. Others
|
||||||
constructor can be emitted via %rename */
|
constructor can be emitted via %rename */
|
||||||
int handled_as_init = 0;
|
int handled_as_init = 0;
|
||||||
|
|
@ -1946,25 +1945,21 @@ public:
|
||||||
// (the smart-pointer) and the director object (the "pointee") are
|
// (the smart-pointer) and the director object (the "pointee") are
|
||||||
// distinct.
|
// distinct.
|
||||||
|
|
||||||
if (directorsEnabled()) {
|
director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
|
||||||
if (!is_smart_pointer()) {
|
if (director_method) {
|
||||||
if (/*directorbase &&*/ !constructor && !destructor
|
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
||||||
&& isVirtual && !Getattr(n,"feature:nodirector")) {
|
Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
|
||||||
director_method = 1;
|
if (dirprot_mode() && !is_public(n)) {
|
||||||
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
|
||||||
Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
|
Printf(f->code, "SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
|
||||||
if (dirprot_mode() && !is_public(n)) {
|
Append(f->code, "SWIG_fail;\n");
|
||||||
Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
|
Append(f->code, "}\n");
|
||||||
Printf(f->code, "SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
|
}
|
||||||
Append(f->code, "SWIG_fail;\n");
|
Wrapper_add_local(f, "upcall", "bool upcall = false");
|
||||||
Append(f->code, "}\n");
|
if (funpack) {
|
||||||
}
|
Append(f->code, "upcall = (director && (director->swig_get_self()==swig_obj[0]));\n");
|
||||||
if (funpack) {
|
} else {
|
||||||
Append(f->code, "if (director && (director->swig_get_self()==swig_obj[0])) director->swig_set_up();\n");
|
Append(f->code, "upcall = (director && (director->swig_get_self()==obj0));\n");
|
||||||
} else {
|
|
||||||
Append(f->code, "if (director && (director->swig_get_self()==obj0)) director->swig_set_up();\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3570,29 +3565,12 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
|
||||||
p = nextSibling(p);
|
p = nextSibling(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add the method name as a PyString */
|
||||||
/* add the method name as a PyString */
|
|
||||||
String *pyname = Getattr(n,"sym:name");
|
String *pyname = Getattr(n,"sym:name");
|
||||||
|
|
||||||
int allow_thread = threads_enable(n);
|
int allow_thread = threads_enable(n);
|
||||||
|
|
||||||
/* direct call to superclass if _up is set */
|
|
||||||
if (allow_thread) thread_begin_block(n, w->code);
|
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
|
/* declare method return value
|
||||||
* if the return value is a reference or const reference, a specialized typemap must
|
* 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");
|
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 */
|
/* emit the director method */
|
||||||
if (status == SWIG_OK) {
|
if (status == SWIG_OK) {
|
||||||
if (!Getattr(n,"defaultargs")) {
|
if (!Getattr(n,"defaultargs")) {
|
||||||
Wrapper_print(w, f_directors);
|
Wrapper_print(w, f_directors);
|
||||||
Printv(f_directors_h, declaration, NIL);
|
Printv(f_directors_h, declaration, NIL);
|
||||||
|
Printv(f_directors_h, inline_extra_method, NIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -991,7 +991,6 @@ public:
|
||||||
bool constructor;
|
bool constructor;
|
||||||
bool destructor;
|
bool destructor;
|
||||||
String *storage;
|
String *storage;
|
||||||
bool isVirtual;
|
|
||||||
|
|
||||||
String *symname = Copy(Getattr(n,"sym:name"));
|
String *symname = Copy(Getattr(n,"sym:name"));
|
||||||
SwigType *t = Getattr(n,"type");
|
SwigType *t = Getattr(n,"type");
|
||||||
|
|
@ -1009,7 +1008,6 @@ public:
|
||||||
constructor = (!Cmp(nodeType, "constructor"));
|
constructor = (!Cmp(nodeType, "constructor"));
|
||||||
destructor = (!Cmp(nodeType, "destructor"));
|
destructor = (!Cmp(nodeType, "destructor"));
|
||||||
storage = Getattr(n, "storage");
|
storage = Getattr(n, "storage");
|
||||||
isVirtual = (Cmp(storage, "virtual") == 0);
|
|
||||||
|
|
||||||
/* If the C++ class constructor is overloaded, we only want to
|
/* If the C++ class constructor is overloaded, we only want to
|
||||||
* write out the "new" singleton method once since it is always
|
* 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
|
// (the smart-pointer) and the director object (the "pointee") are
|
||||||
// distinct.
|
// distinct.
|
||||||
|
|
||||||
if (directorsEnabled()) {
|
director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
|
||||||
if (!is_smart_pointer()) {
|
if (director_method) {
|
||||||
if (/*directorbase &&*/ !constructor && !destructor
|
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
||||||
&& isVirtual && !Getattr(n,"feature:nodirector")) {
|
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
|
||||||
director_method = 1;
|
Wrapper_add_local(f, "upcall", "bool upcall = false");
|
||||||
Wrapper_add_local(f, "director", "Swig::Director *director = 0");
|
Append(f->code, "upcall = (director && (director->swig_get_self() == self));\n");
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now write code to make the function call */
|
/* Now write code to make the function call */
|
||||||
|
|
@ -2484,20 +2478,6 @@ public:
|
||||||
/* declare Ruby return value */
|
/* declare Ruby return value */
|
||||||
Wrapper_add_local(w, "result", "VALUE result");
|
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 */
|
/* wrap complex arguments to VALUEs */
|
||||||
Printv(w->code, wrap_args, NIL);
|
Printv(w->code, wrap_args, NIL);
|
||||||
|
|
||||||
|
|
@ -2588,14 +2568,30 @@ public:
|
||||||
}
|
}
|
||||||
Delete(rettype);
|
Delete(rettype);
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf(w->code, "}\n");
|
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 */
|
/* emit the director method */
|
||||||
if (status == SWIG_OK) {
|
if (status == SWIG_OK) {
|
||||||
if (!Getattr(n,"defaultargs")) {
|
if (!Getattr(n,"defaultargs")) {
|
||||||
Wrapper_print(w, f_directors);
|
Wrapper_print(w, f_directors);
|
||||||
Printv(f_directors_h, declaration, NIL);
|
Printv(f_directors_h, declaration, NIL);
|
||||||
|
Printv(f_directors_h, inline_extra_method, NIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,9 @@ protected:
|
||||||
/* Return true if the current method is part of a smart-pointer */
|
/* Return true if the current method is part of a smart-pointer */
|
||||||
int is_smart_pointer() const;
|
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 */
|
/* Director subclass comparison test */
|
||||||
String *none_comparison;
|
String *none_comparison;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -382,7 +382,7 @@ Swig_cfunction_call(String_or_char *name, ParmList *parms) {
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static String *
|
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;
|
String *func, *nname;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Parm *p = parms;
|
Parm *p = parms;
|
||||||
|
|
@ -402,36 +402,44 @@ Swig_cmethod_call(String_or_char *name, ParmList *parms, String_or_char *self, S
|
||||||
} else {
|
} else {
|
||||||
nname = SwigType_namestr(name);
|
nname = SwigType_namestr(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pt = Getattr(p,k_type);
|
|
||||||
|
|
||||||
/* If the method is invoked through a dereferenced pointer, we don't add any casts
|
if (director_type) {
|
||||||
(needed for smart pointers). Otherwise, we cast to the appropriate type */
|
const char *pname = "darg";
|
||||||
|
String *rcaststr = SwigType_rcaststr(director_type, pname);
|
||||||
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);
|
Replaceall(func,"this", rcaststr);
|
||||||
Delete(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);
|
Printf(func,"%s(", nname);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -787,7 +795,7 @@ Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms,
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int
|
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;
|
String *name, *qualifier;
|
||||||
ParmList *parms;
|
ParmList *parms;
|
||||||
SwigType *type;
|
SwigType *type;
|
||||||
|
|
@ -845,13 +853,51 @@ Swig_MethodToFunction(Node *n, String *classname, int flags) {
|
||||||
|
|
||||||
/* Generate action code for the access */
|
/* Generate action code for the access */
|
||||||
if (!(flags & CWRAP_EXTEND)) {
|
if (!(flags & CWRAP_EXTEND)) {
|
||||||
/* Call the explicit method rather than allow for a polymorphic call */
|
String *explicit_qualifier = 0;
|
||||||
String *explicit_qualifier = GetFlag(n,"explicitcall") ?
|
String *call = 0;
|
||||||
SwigType_namestr(Getattr(Getattr(parentNode(n),"typescope"),k_qname)) : 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);
|
/* Call the explicit method rather than allow for a polymorphic call */
|
||||||
String *cres = Swig_cresult(Getattr(n,k_type),k_result, call);
|
if ((flags & CWRAP_DIRECTOR_TWO_CALLS) || (flags & CWRAP_DIRECTOR_ONE_CALL)) {
|
||||||
Setattr(n,k_wrapaction, cres);
|
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(call);
|
||||||
Delete(cres);
|
Delete(cres);
|
||||||
Delete(explicit_qualifier);
|
Delete(explicit_qualifier);
|
||||||
|
|
|
||||||
|
|
@ -494,7 +494,7 @@ extern int Swig_add_extension_code(Node *n, const String *function_name,
|
||||||
|
|
||||||
/* --- Transformations --- */
|
/* --- 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,
|
extern int Swig_ConstructorToFunction(Node *n, String *classname,
|
||||||
String *none_comparison,
|
String *none_comparison,
|
||||||
String *director_ctor,
|
String *director_ctor,
|
||||||
|
|
@ -508,6 +508,8 @@ extern int Swig_VarsetToFunction(Node *n, int flags);
|
||||||
#define CWRAP_EXTEND 0x01
|
#define CWRAP_EXTEND 0x01
|
||||||
#define CWRAP_SMART_POINTER 0x02
|
#define CWRAP_SMART_POINTER 0x02
|
||||||
#define CWRAP_NATURAL_VAR 0x04
|
#define CWRAP_NATURAL_VAR 0x04
|
||||||
|
#define CWRAP_DIRECTOR_ONE_CALL 0x08
|
||||||
|
#define CWRAP_DIRECTOR_TWO_CALLS 0x10
|
||||||
|
|
||||||
/* --- Director Helpers --- */
|
/* --- Director Helpers --- */
|
||||||
extern Node *Swig_methodclass(Node *n);
|
extern Node *Swig_methodclass(Node *n);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue