merge from trunk
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2009-sploving@11489 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
commit
21671f7534
86 changed files with 3689 additions and 502 deletions
|
|
@ -1,6 +1,46 @@
|
||||||
Version 1.3.40 (in progress)
|
Version 1.3.40 (in progress)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
2009-07-31: olly
|
||||||
|
[Python] Fix indentation so that we give a useful error if the
|
||||||
|
module can't be loaded. Patch from Gaetan Lehmann in SF#2829853.
|
||||||
|
|
||||||
|
2009-07-29: wsfulton
|
||||||
|
Add $typemap(method, typelist) special variable macro. This allows
|
||||||
|
the contents of a typemap to be inserted within another typemap.
|
||||||
|
Fully documented in Typemaps.html.
|
||||||
|
|
||||||
|
2009-07-29: vmiklos
|
||||||
|
[PHP] Static member variables are now prefixed with the
|
||||||
|
class name. This allows static member variables with the
|
||||||
|
same name in different classes.
|
||||||
|
|
||||||
|
2009-07-29: olly
|
||||||
|
[Python] Add missing locks to std::map wrappers. Patch from
|
||||||
|
Paul Hampson in SF#2813836.
|
||||||
|
|
||||||
|
2009-07-29: olly
|
||||||
|
[PHP] Fix memory leak in PHP OUTPUT typemaps. Reported by Hitoshi
|
||||||
|
Amano in SF#2826322.
|
||||||
|
|
||||||
|
2009-07-29: olly
|
||||||
|
[PHP] Fix memory leak in PHP resource destructor for classes
|
||||||
|
without a destructor and non-class types. Patch from Hitoshi Amano
|
||||||
|
in SF#2825303.
|
||||||
|
|
||||||
|
2009-07-28: olly
|
||||||
|
[PHP] Update warnings about clashes between identifiers and PHP
|
||||||
|
keywords and automatic renaming to work with the PHP5 class
|
||||||
|
wrappers. Fixes SF#1613679.
|
||||||
|
|
||||||
|
2009-07-28: vmiklos
|
||||||
|
[PHP] If a member function is not public but it has a base
|
||||||
|
which is public, then now a warning is issued and the member
|
||||||
|
function will be public, as PHP requires this.
|
||||||
|
|
||||||
|
2009-07-21: vmiklos
|
||||||
|
[PHP] Director support added.
|
||||||
|
|
||||||
2009-07-15: olly
|
2009-07-15: olly
|
||||||
[Perl] Don't specify Perl prototype "()" for a constructor with a
|
[Perl] Don't specify Perl prototype "()" for a constructor with a
|
||||||
different name to the class, as such constructors can still take
|
different name to the class, as such constructors can still take
|
||||||
|
|
@ -17,6 +57,10 @@ Version 1.3.40 (in progress)
|
||||||
of the manual. Based on patch from SF#2810380 by Christian
|
of the manual. Based on patch from SF#2810380 by Christian
|
||||||
Gollwitzer.
|
Gollwitzer.
|
||||||
|
|
||||||
|
2009-07-02: vmiklos
|
||||||
|
[PHP] Added factory.i for PHP, see the li_factory testcase
|
||||||
|
for more info on how to use it.
|
||||||
|
|
||||||
2009-07-02: wsfulton
|
2009-07-02: wsfulton
|
||||||
Fix -Wallkw option as reported by Solomon Gibbs.
|
Fix -Wallkw option as reported by Solomon Gibbs.
|
||||||
|
|
||||||
|
|
@ -24,6 +68,14 @@ Version 1.3.40 (in progress)
|
||||||
Fix syntax error when a nested struct contains a comment containing a * followed eventually by a /.
|
Fix syntax error when a nested struct contains a comment containing a * followed eventually by a /.
|
||||||
Regression from 1.3.37, reported by Solomon Gibbs.
|
Regression from 1.3.37, reported by Solomon Gibbs.
|
||||||
|
|
||||||
|
2009-07-01: vmiklos
|
||||||
|
[PHP] Unknown properties are no longer ignored in proxy
|
||||||
|
classes.
|
||||||
|
|
||||||
|
2009-07-01: vmiklos
|
||||||
|
[PHP] Fixed %newobject behaviour, previously any method
|
||||||
|
marked with %newobject was handled as a constructor.
|
||||||
|
|
||||||
2009-06-30: olly
|
2009-06-30: olly
|
||||||
[Ruby] Undefine close and connect macros defined by Ruby API
|
[Ruby] Undefine close and connect macros defined by Ruby API
|
||||||
headers as we don't need them and they can clash with C++ methods
|
headers as we don't need them and they can clash with C++ methods
|
||||||
|
|
@ -66,6 +118,12 @@ Version 1.3.40 (in progress)
|
||||||
|
|
||||||
*** POTENTIAL INCOMPATIBILITY ***
|
*** POTENTIAL INCOMPATIBILITY ***
|
||||||
|
|
||||||
|
2009-05-20: vmiklos
|
||||||
|
[PHP] Add the 'thisown' member to classes. The usage of it
|
||||||
|
is the same as the Python thisown one: it's 1 by default and
|
||||||
|
you can set it to 0 if you want to prevent freeing it. (For
|
||||||
|
example to prevent a double free.)
|
||||||
|
|
||||||
2009-05-14: bhy
|
2009-05-14: bhy
|
||||||
[Python] Fix the wrong pointer value returned by SwigPyObject_repr().
|
[Python] Fix the wrong pointer value returned by SwigPyObject_repr().
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -337,13 +337,13 @@
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn10">Typemap specifications</a>
|
<li><a href="Typemaps.html#Typemaps_nn10">Typemap specifications</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn11">Defining a typemap</a>
|
<li><a href="Typemaps.html#Typemaps_defining">Defining a typemap</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn12">Typemap scope</a>
|
<li><a href="Typemaps.html#Typemaps_nn12">Typemap scope</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn13">Copying a typemap</a>
|
<li><a href="Typemaps.html#Typemaps_nn13">Copying a typemap</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn14">Deleting a typemap</a>
|
<li><a href="Typemaps.html#Typemaps_nn14">Deleting a typemap</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn15">Placement of typemaps</a>
|
<li><a href="Typemaps.html#Typemaps_nn15">Placement of typemaps</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn16">Pattern matching rules</a>
|
<li><a href="Typemaps.html#Typemaps_pattern_matching">Pattern matching rules</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn17">Basic matching rules</a>
|
<li><a href="Typemaps.html#Typemaps_nn17">Basic matching rules</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn18">Typedef reductions</a>
|
<li><a href="Typemaps.html#Typemaps_nn18">Typedef reductions</a>
|
||||||
|
|
@ -356,6 +356,11 @@
|
||||||
<li><a href="Typemaps.html#Typemaps_nn22">Scope</a>
|
<li><a href="Typemaps.html#Typemaps_nn22">Scope</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn23">Declaring new local variables</a>
|
<li><a href="Typemaps.html#Typemaps_nn23">Declaring new local variables</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_special_variables">Special variables</a>
|
<li><a href="Typemaps.html#Typemaps_special_variables">Special variables</a>
|
||||||
|
<li><a href="Typemaps.html#Typemaps_special_variable_macros">Special variable macros</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="Typemaps.html#Typemaps_special_macro_descriptor">$descriptor(type)</a>
|
||||||
|
<li><a href="Typemaps.html#Typemaps_special_macro_typemap">$typemap(method, typepattern)</a>
|
||||||
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn25">Common typemap methods</a>
|
<li><a href="Typemaps.html#Typemaps_nn25">Common typemap methods</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -384,7 +389,7 @@
|
||||||
<li><a href="Typemaps.html#runtime_type_checker">The run-time type checker</a>
|
<li><a href="Typemaps.html#runtime_type_checker">The run-time type checker</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn45">Implementation</a>
|
<li><a href="Typemaps.html#Typemaps_nn45">Implementation</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn46">Usage</a>
|
<li><a href="Typemaps.html#Typemaps_runtime_type_checker_usage">Usage</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="Typemaps.html#Typemaps_overloading">Typemaps and overloading</a>
|
<li><a href="Typemaps.html#Typemaps_overloading">Typemaps and overloading</a>
|
||||||
<li><a href="Typemaps.html#Typemaps_nn48">More about <tt>%apply</tt> and <tt>%clear</tt></a>
|
<li><a href="Typemaps.html#Typemaps_nn48">More about <tt>%apply</tt> and <tt>%clear</tt></a>
|
||||||
|
|
@ -1115,7 +1120,7 @@
|
||||||
<li><a href="Perl5.html#Perl5_nn24">Modules and packages</a>
|
<li><a href="Perl5.html#Perl5_nn24">Modules and packages</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="Perl5.html#Perl5_nn25">Input and output parameters</a>
|
<li><a href="Perl5.html#Perl5_nn25">Input and output parameters</a>
|
||||||
<li><a href="Perl5.html#Perl5_nn26">Exception handling </a>
|
<li><a href="Perl5.html#Perl5_nn26">Exception handling</a>
|
||||||
<li><a href="Perl5.html#Perl5_nn27">Remapping datatypes with typemaps</a>
|
<li><a href="Perl5.html#Perl5_nn27">Remapping datatypes with typemaps</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="Perl5.html#Perl5_nn28">A simple typemap example</a>
|
<li><a href="Perl5.html#Perl5_nn28">A simple typemap example</a>
|
||||||
|
|
@ -1125,8 +1130,8 @@
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="Perl5.html#Perl5_nn32">Typemap Examples</a>
|
<li><a href="Perl5.html#Perl5_nn32">Typemap Examples</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="Perl5.html#Perl5_nn33">Converting a Perl5 array to a char ** </a>
|
<li><a href="Perl5.html#Perl5_nn33">Converting a Perl5 array to a char **</a>
|
||||||
<li><a href="Perl5.html#Perl5_nn34">Return values </a>
|
<li><a href="Perl5.html#Perl5_nn34">Return values</a>
|
||||||
<li><a href="Perl5.html#Perl5_nn35">Returning values from arguments</a>
|
<li><a href="Perl5.html#Perl5_nn35">Returning values from arguments</a>
|
||||||
<li><a href="Perl5.html#Perl5_nn36">Accessing array structure members</a>
|
<li><a href="Perl5.html#Perl5_nn36">Accessing array structure members</a>
|
||||||
<li><a href="Perl5.html#Perl5_nn37">Turning Perl references into C pointers</a>
|
<li><a href="Perl5.html#Perl5_nn37">Turning Perl references into C pointers</a>
|
||||||
|
|
@ -1173,6 +1178,16 @@
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="Php.html#Php_nn2_7">PHP Pragmas, Startup and Shutdown code</a>
|
<li><a href="Php.html#Php_nn2_7">PHP Pragmas, Startup and Shutdown code</a>
|
||||||
</ul>
|
</ul>
|
||||||
|
<li><a href="Php.html#Php_nn3">Cross language polymorphism</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="Php.html#Php_nn3_1">Enabling directors</a>
|
||||||
|
<li><a href="Php.html#Php_nn3_2">Director classes</a>
|
||||||
|
<li><a href="Php.html#Php_nn3_3">Ownership and object destruction</a>
|
||||||
|
<li><a href="Php.html#Php_nn3_4">Exception unrolling</a>
|
||||||
|
<li><a href="Php.html#Php_nn3_5">Overhead and code bloat</a>
|
||||||
|
<li><a href="Php.html#Php_nn3_6">Typemaps</a>
|
||||||
|
<li><a href="Php.html#Php_nn3_7">Miscellaneous</a>
|
||||||
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<!-- INDEX -->
|
<!-- INDEX -->
|
||||||
|
|
@ -1502,6 +1517,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="Tcl.html#Tcl_nn45">Proxy classes</a>
|
<li><a href="Tcl.html#Tcl_nn45">Proxy classes</a>
|
||||||
</ul>
|
</ul>
|
||||||
|
<li><a href="Tcl.html#Tcl_nn46">Tcl/Tk Stubs</a>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<!-- INDEX -->
|
<!-- INDEX -->
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,16 @@
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#Php_nn2_7">PHP Pragmas, Startup and Shutdown code</a>
|
<li><a href="#Php_nn2_7">PHP Pragmas, Startup and Shutdown code</a>
|
||||||
</ul>
|
</ul>
|
||||||
|
<li><a href="#Php_nn3">Cross language polymorphism</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#Php_nn3_1">Enabling directors</a>
|
||||||
|
<li><a href="#Php_nn3_2">Director classes</a>
|
||||||
|
<li><a href="#Php_nn3_3">Ownership and object destruction</a>
|
||||||
|
<li><a href="#Php_nn3_4">Exception unrolling</a>
|
||||||
|
<li><a href="#Php_nn3_5">Overhead and code bloat</a>
|
||||||
|
<li><a href="#Php_nn3_6">Typemaps</a>
|
||||||
|
<li><a href="#Php_nn3_7">Miscellaneous</a>
|
||||||
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<!-- INDEX -->
|
<!-- INDEX -->
|
||||||
|
|
@ -866,5 +876,381 @@ The <tt>%rinit</tt> and <tt>%rshutdown</tt> statements insert code
|
||||||
into the request init and shutdown code respectively.
|
into the request init and shutdown code respectively.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<H2><a name="Php_nn3"></a>29.3 Cross language polymorphism</H2>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Proxy classes provide a more natural, object-oriented way to access
|
||||||
|
extension classes. As described above, each proxy instance has an
|
||||||
|
associated C++ instance, and method calls to the proxy are passed to the
|
||||||
|
C++ instance transparently via C wrapper functions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This arrangement is asymmetric in the sense that no corresponding
|
||||||
|
mechanism exists to pass method calls down the inheritance chain from
|
||||||
|
C++ to PHP. In particular, if a C++ class has been extended in PHP
|
||||||
|
(by extending the proxy class), these extensions will not be visible
|
||||||
|
from C++ code. Virtual method calls from C++ are thus not able access
|
||||||
|
the lowest implementation in the inheritance chain.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Changes have been made to SWIG 1.3.18 to address this problem and make
|
||||||
|
the relationship between C++ classes and proxy classes more symmetric.
|
||||||
|
To achieve this goal, new classes called directors are introduced at the
|
||||||
|
bottom of the C++ inheritance chain. Support for generating PHP classes
|
||||||
|
has been added in SWIG 1.3.40. The job of the directors is to route
|
||||||
|
method calls correctly, either to C++ implementations higher in the
|
||||||
|
inheritance chain or to PHP implementations lower in the inheritance
|
||||||
|
chain. The upshot is that C++ classes can be extended in PHP and from
|
||||||
|
C++ these extensions look exactly like native C++ classes. Neither C++
|
||||||
|
code nor PHP code needs to know where a particular method is
|
||||||
|
implemented: the combination of proxy classes, director classes, and C
|
||||||
|
wrapper functions takes care of all the cross-language method routing
|
||||||
|
transparently.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<H3><a name="Php_nn3_1"></a>29.3.1 Enabling directors</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The director feature is disabled by default. To use directors you
|
||||||
|
must make two changes to the interface file. First, add the "directors"
|
||||||
|
option to the %module directive, like this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%module(directors="1") modulename
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Without this option no director code will be generated. Second, you
|
||||||
|
must use the %feature("director") directive to tell SWIG which classes
|
||||||
|
and methods should get directors. The %feature directive can be applied
|
||||||
|
globally, to specific classes, and to specific methods, like this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
// generate directors for all classes that have virtual methods
|
||||||
|
%feature("director");
|
||||||
|
|
||||||
|
// generate directors for all virtual methods in class Foo
|
||||||
|
%feature("director") Foo;
|
||||||
|
|
||||||
|
// generate a director for just Foo::bar()
|
||||||
|
%feature("director") Foo::bar;
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can use the %feature("nodirector") directive to turn off
|
||||||
|
directors for specific classes or methods. So for example,
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%feature("director") Foo;
|
||||||
|
%feature("nodirector") Foo::bar;
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
will generate directors for all virtual methods of class Foo except
|
||||||
|
bar().
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Directors can also be generated implicitly through inheritance.
|
||||||
|
In the following, class Bar will get a director class that handles
|
||||||
|
the methods one() and two() (but not three()):
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%feature("director") Foo;
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
Foo(int foo);
|
||||||
|
virtual void one();
|
||||||
|
virtual void two();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Bar: public Foo {
|
||||||
|
public:
|
||||||
|
virtual void three();
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
then at the PHP side you can define
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="targetlang">
|
||||||
|
<pre>
|
||||||
|
require("mymodule.php");
|
||||||
|
|
||||||
|
class MyFoo extends Foo {
|
||||||
|
function one() {
|
||||||
|
print "one from php\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<H3><a name="Php_nn3_2"></a>29.3.2 Director classes</H3>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For each class that has directors enabled, SWIG generates a new class
|
||||||
|
that derives from both the class in question and a special
|
||||||
|
<tt>Swig::Director</tt> class. These new classes, referred to as director
|
||||||
|
classes, can be loosely thought of as the C++ equivalent of the PHP
|
||||||
|
proxy classes. The director classes store a pointer to their underlying
|
||||||
|
PHP object. Indeed, this is quite similar to the "_cPtr" and "thisown"
|
||||||
|
members of the PHP proxy classes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For simplicity let's ignore the <tt>Swig::Director</tt> class and refer to the
|
||||||
|
original C++ class as the director's base class. By default, a director
|
||||||
|
class extends all virtual methods in the inheritance chain of its base
|
||||||
|
class (see the preceding section for how to modify this behavior).
|
||||||
|
Thus all virtual method calls, whether they originate in C++ or in
|
||||||
|
PHP via proxy classes, eventually end up in at the implementation in the
|
||||||
|
director class. The job of the director methods is to route these method
|
||||||
|
calls to the appropriate place in the inheritance chain. By "appropriate
|
||||||
|
place" we mean the method that would have been called if the C++ base
|
||||||
|
class and its extensions in PHP were seamlessly integrated. That
|
||||||
|
seamless integration is exactly what the director classes provide,
|
||||||
|
transparently skipping over all the messy extension API glue that binds
|
||||||
|
the two languages together.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In reality, the "appropriate place" is one of only two possibilities:
|
||||||
|
C++ or PHP. Once this decision is made, the rest is fairly easy. If the
|
||||||
|
correct implementation is in C++, then the lowest implementation of the
|
||||||
|
method in the C++ inheritance chain is called explicitly. If the correct
|
||||||
|
implementation is in PHP, the Zend API is used to call the method of the
|
||||||
|
underlying PHP object (after which the usual virtual method resolution
|
||||||
|
in PHP automatically finds the right implementation).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Now how does the director decide which language should handle the method call?
|
||||||
|
The basic rule is to handle the method in PHP, unless there's a good
|
||||||
|
reason not to. The reason for this is simple: PHP has the most
|
||||||
|
"extended" implementation of the method. This assertion is guaranteed,
|
||||||
|
since at a minimum the PHP proxy class implements the method. If the
|
||||||
|
method in question has been extended by a class derived from the proxy
|
||||||
|
class, that extended implementation will execute exactly as it should.
|
||||||
|
If not, the proxy class will route the method call into a C wrapper
|
||||||
|
function, expecting that the method will be resolved in C++. The wrapper
|
||||||
|
will call the virtual method of the C++ instance, and since the director
|
||||||
|
extends this the call will end up right back in the director method. Now
|
||||||
|
comes the "good reason not to" part. If the director method were to blindly
|
||||||
|
call the PHP method again, it would get stuck in an infinite loop. We avoid this
|
||||||
|
situation by adding special code to the C wrapper function that tells
|
||||||
|
the director method to not do this. The C wrapper function compares the
|
||||||
|
called and the declaring class name of the given method. If these are
|
||||||
|
not the same, then the C wrapper function tells the director to resolve
|
||||||
|
the method by calling up the C++ inheritance chain, preventing an
|
||||||
|
infinite loop.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
One more point needs to be made about the relationship between director
|
||||||
|
classes and proxy classes. When a proxy class instance is created in
|
||||||
|
PHP, SWIG creates an instance of the original C++ class and assigns it
|
||||||
|
to <tt>->_cPtr</tt>. This is exactly what happens without directors
|
||||||
|
and is true even if directors are enabled for the particular class in
|
||||||
|
question. When a class <i>derived</i> from a proxy class is created,
|
||||||
|
however, SWIG then creates an instance of the corresponding C++ director
|
||||||
|
class. The reason for this difference is that user-defined subclasses
|
||||||
|
may override or extend methods of the original class, so the director
|
||||||
|
class is needed to route calls to these methods correctly. For
|
||||||
|
unmodified proxy classes, all methods are ultimately implemented in C++
|
||||||
|
so there is no need for the extra overhead involved with routing the
|
||||||
|
calls through PHP.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<H3><a name="Php_nn3_3"></a>29.3.3 Ownership and object destruction</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Memory management issues are slightly more complicated with directors
|
||||||
|
than for proxy classes alone. PHP instances hold a pointer to the
|
||||||
|
associated C++ director object, and the director in turn holds a pointer
|
||||||
|
back to the PHP object. By default, proxy classes own their C++ director
|
||||||
|
object and take care of deleting it when they are garbage collected.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This relationship can be reversed by calling the special
|
||||||
|
<tt>->thisown</tt> property of the proxy class. After setting this
|
||||||
|
property to <tt>0</tt>, the director class no longer destroys the PHP
|
||||||
|
object. Assuming no outstanding references to the PHP object remain,
|
||||||
|
the PHP object will be destroyed at the same time. This is a good thing,
|
||||||
|
since directors and proxies refer to each other and so must be created
|
||||||
|
and destroyed together. Destroying one without destroying the other will
|
||||||
|
likely cause your program to segfault.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here is an example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
};
|
||||||
|
class FooContainer {
|
||||||
|
public:
|
||||||
|
void addFoo(Foo *);
|
||||||
|
...
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="targetlang">
|
||||||
|
<pre>
|
||||||
|
$c = new FooContainer();
|
||||||
|
$a = new Foo();
|
||||||
|
$a->thisown = 0;
|
||||||
|
$c->addFoo($a);
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In this example, we are assuming that FooContainer will take care of
|
||||||
|
deleting all the Foo pointers it contains at some point.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<H3><a name="Php_nn3_4"></a>29.3.4 Exception unrolling</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
With directors routing method calls to PHP, and proxies routing them
|
||||||
|
to C++, the handling of exceptions is an important concern. By default, the
|
||||||
|
directors ignore exceptions that occur during method calls that are
|
||||||
|
resolved in PHP. To handle such exceptions correctly, it is necessary
|
||||||
|
to temporarily translate them into C++ exceptions. This can be done with
|
||||||
|
the %feature("director:except") directive. The following code should
|
||||||
|
suffice in most cases:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%feature("director:except") {
|
||||||
|
if ($error == FAILURE) {
|
||||||
|
throw Swig::DirectorMethodException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This code will check the PHP error state after each method call from a
|
||||||
|
director into PHP, and throw a C++ exception if an error occurred. This
|
||||||
|
exception can be caught in C++ to implement an error handler.
|
||||||
|
Currently no information about the PHP error is stored in the
|
||||||
|
Swig::DirectorMethodException object, but this will likely change in the
|
||||||
|
future.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
It may be the case that a method call originates in PHP, travels up to
|
||||||
|
C++ through a proxy class, and then back into PHP via a director method.
|
||||||
|
If an exception occurs in PHP at this point, it would be nice for that
|
||||||
|
exception to find its way back to the original caller. This can be done
|
||||||
|
by combining a normal %exception directive with the
|
||||||
|
<tt>director:except</tt> handler shown above. Here is an example of a
|
||||||
|
suitable exception handler:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%exception {
|
||||||
|
try { $action }
|
||||||
|
catch (Swig::DirectorException &e) { SWIG_fail; }
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The class Swig::DirectorException used in this example is actually a
|
||||||
|
base class of Swig::DirectorMethodException, so it will trap this
|
||||||
|
exception. Because the PHP error state is still set when
|
||||||
|
Swig::DirectorMethodException is thrown, PHP will register the exception
|
||||||
|
as soon as the C wrapper function returns.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<H3><a name="Php_nn3_5"></a>29.3.5 Overhead and code bloat</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Enabling directors for a class will generate a new director method for
|
||||||
|
every virtual method in the class' inheritance chain. This alone can
|
||||||
|
generate a lot of code bloat for large hierarchies. Method arguments
|
||||||
|
that require complex conversions to and from target language types can
|
||||||
|
result in large director methods. For this reason it is recommended that
|
||||||
|
you selectively enable directors only for specific classes that are
|
||||||
|
likely to be extended in PHP and used in C++.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Compared to classes that do not use directors, the call routing in the
|
||||||
|
director methods does add some overhead. In particular, at least one
|
||||||
|
dynamic cast and one extra function call occurs per method call from
|
||||||
|
PHP. Relative to the speed of PHP execution this is probably completely
|
||||||
|
negligible. For worst case routing, a method call that ultimately
|
||||||
|
resolves in C++ may take one extra detour through PHP in order to ensure
|
||||||
|
that the method does not have an extended PHP implementation. This could
|
||||||
|
result in a noticeable overhead in some cases.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Although directors make it natural to mix native C++ objects with PHP
|
||||||
|
objects (as director objects) via a common base class pointer, one
|
||||||
|
should be aware of the obvious fact that method calls to PHP objects
|
||||||
|
will be much slower than calls to C++ objects. This situation can be
|
||||||
|
optimized by selectively enabling director methods (using the %feature
|
||||||
|
directive) for only those methods that are likely to be extended in PHP.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<H3><a name="Php_nn3_6"></a>29.3.6 Typemaps</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Typemaps for input and output of most of the basic types from director
|
||||||
|
classes have been written. These are roughly the reverse of the usual
|
||||||
|
input and output typemaps used by the wrapper code. The typemap
|
||||||
|
operation names are 'directorin', 'directorout', and 'directorargout'.
|
||||||
|
The director code does not currently use any of the other kinds of
|
||||||
|
typemaps. It is not clear at this point which kinds are appropriate and
|
||||||
|
need to be supported.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<H3><a name="Php_nn3_7"></a>29.3.7 Miscellaneous</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p> Director typemaps for STL classes are mostly in place, and hence you
|
||||||
|
should be able to use std::string, etc., as you would any other type.
|
||||||
|
</p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@
|
||||||
<li><a href="#scilab_nn10">Global variables</a>
|
<li><a href="#scilab_nn10">Global variables</a>
|
||||||
<li><a href="#Scilab_nn11">Constants</a>
|
<li><a href="#Scilab_nn11">Constants</a>
|
||||||
<li><a href="#Scilab_nn12">Enums</a>
|
<li><a href="#Scilab_nn12">Enums</a>
|
||||||
<li><a href="#Octave_nn13">Pointers</a>
|
<li><a href="#Scilab_nn13">Pointers</a>
|
||||||
<li><a href="#Octave_nn14">Structs</a>
|
<li><a href="#Scilab_nn14">Structs</a>
|
||||||
</ul>
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -315,7 +315,7 @@ scilab:4> printf(" GREEN = %i\n", color.GREEN);
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
|
|
||||||
<H3><a name="Octave_nn13"></a>27.3.5 Pointers</H3>
|
<H3><a name="Scilab_nn13"></a>27.3.5 Pointers</H3>
|
||||||
<p>
|
<p>
|
||||||
Pointers are fully supported by SWIG. One way to deal with the pointers is using the INPUT and OUTPUT typemaps. For example, in order to call C functions as the following:
|
Pointers are fully supported by SWIG. One way to deal with the pointers is using the INPUT and OUTPUT typemaps. For example, in order to call C functions as the following:
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -356,7 +356,7 @@ scilab:4> printf(" 42/37 = %d remainder %d\n",q,r);
|
||||||
we only need a real value instead.
|
we only need a real value instead.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H3><a name="Octave_nn14"></a>27.3.6 Structs</H3>
|
<H3><a name="Scilab_nn14"></a>27.3.6 Structs</H3>
|
||||||
<p>
|
<p>
|
||||||
SWIG creates a set of accessor functions when encountering a structure or union. For example:
|
SWIG creates a set of accessor functions when encountering a structure or union. For example:
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -3412,6 +3412,7 @@ interesting things.
|
||||||
|
|
||||||
<H2><a name="Tcl_nn46"></a>33.10 Tcl/Tk Stubs</H2>
|
<H2><a name="Tcl_nn46"></a>33.10 Tcl/Tk Stubs</H2>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
For background information about the Tcl Stubs feature, see
|
For background information about the Tcl Stubs feature, see
|
||||||
<a href="http://www.tcl.tk/doc/howto/stubs.html">http://www.tcl.tk/doc/howto/stubs.html</a>.
|
<a href="http://www.tcl.tk/doc/howto/stubs.html">http://www.tcl.tk/doc/howto/stubs.html</a>.
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#Typemaps_nn10">Typemap specifications</a>
|
<li><a href="#Typemaps_nn10">Typemap specifications</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#Typemaps_nn11">Defining a typemap</a>
|
<li><a href="#Typemaps_defining">Defining a typemap</a>
|
||||||
<li><a href="#Typemaps_nn12">Typemap scope</a>
|
<li><a href="#Typemaps_nn12">Typemap scope</a>
|
||||||
<li><a href="#Typemaps_nn13">Copying a typemap</a>
|
<li><a href="#Typemaps_nn13">Copying a typemap</a>
|
||||||
<li><a href="#Typemaps_nn14">Deleting a typemap</a>
|
<li><a href="#Typemaps_nn14">Deleting a typemap</a>
|
||||||
<li><a href="#Typemaps_nn15">Placement of typemaps</a>
|
<li><a href="#Typemaps_nn15">Placement of typemaps</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#Typemaps_nn16">Pattern matching rules</a>
|
<li><a href="#Typemaps_pattern_matching">Pattern matching rules</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#Typemaps_nn17">Basic matching rules</a>
|
<li><a href="#Typemaps_nn17">Basic matching rules</a>
|
||||||
<li><a href="#Typemaps_nn18">Typedef reductions</a>
|
<li><a href="#Typemaps_nn18">Typedef reductions</a>
|
||||||
|
|
@ -41,6 +41,11 @@
|
||||||
<li><a href="#Typemaps_nn22">Scope</a>
|
<li><a href="#Typemaps_nn22">Scope</a>
|
||||||
<li><a href="#Typemaps_nn23">Declaring new local variables</a>
|
<li><a href="#Typemaps_nn23">Declaring new local variables</a>
|
||||||
<li><a href="#Typemaps_special_variables">Special variables</a>
|
<li><a href="#Typemaps_special_variables">Special variables</a>
|
||||||
|
<li><a href="#Typemaps_special_variable_macros">Special variable macros</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#Typemaps_special_macro_descriptor">$descriptor(type)</a>
|
||||||
|
<li><a href="#Typemaps_special_macro_typemap">$typemap(method, typepattern)</a>
|
||||||
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#Typemaps_nn25">Common typemap methods</a>
|
<li><a href="#Typemaps_nn25">Common typemap methods</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -69,7 +74,7 @@
|
||||||
<li><a href="#runtime_type_checker">The run-time type checker</a>
|
<li><a href="#runtime_type_checker">The run-time type checker</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#Typemaps_nn45">Implementation</a>
|
<li><a href="#Typemaps_nn45">Implementation</a>
|
||||||
<li><a href="#Typemaps_nn46">Usage</a>
|
<li><a href="#Typemaps_runtime_type_checker_usage">Usage</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#Typemaps_overloading">Typemaps and overloading</a>
|
<li><a href="#Typemaps_overloading">Typemaps and overloading</a>
|
||||||
<li><a href="#Typemaps_nn48">More about <tt>%apply</tt> and <tt>%clear</tt></a>
|
<li><a href="#Typemaps_nn48">More about <tt>%apply</tt> and <tt>%clear</tt></a>
|
||||||
|
|
@ -655,7 +660,7 @@ of "The C Programming Language" by Kernighan and Ritchie or
|
||||||
This section describes the behavior of the <tt>%typemap</tt> directive itself.
|
This section describes the behavior of the <tt>%typemap</tt> directive itself.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H3><a name="Typemaps_nn11"></a>10.2.1 Defining a typemap</H3>
|
<H3><a name="Typemaps_defining"></a>10.2.1 Defining a typemap</H3>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -988,7 +993,7 @@ It should be noted that for scoping to work, SWIG has to know that <tt>string</t
|
||||||
within a particular namespace. In this example, this is done using the class declaration <tt>class string</tt>.
|
within a particular namespace. In this example, this is done using the class declaration <tt>class string</tt>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H2><a name="Typemaps_nn16"></a>10.3 Pattern matching rules</H2>
|
<H2><a name="Typemaps_pattern_matching"></a>10.3 Pattern matching rules</H2>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -1646,6 +1651,7 @@ each type must have its own local variable declaration.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Within all typemaps, the following special variables are expanded.
|
Within all typemaps, the following special variables are expanded.
|
||||||
|
This is by no means a complete list as some target languages have additional special variables which are documented in the language specific chapters.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<center>
|
<center>
|
||||||
|
|
@ -1892,6 +1898,86 @@ Another approach, which only works for arrays is to use the <tt>$1_basetype</tt>
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<H3><a name="Typemaps_special_variable_macros"></a>10.4.4 Special variable macros</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Special variable macros are like macro functions in that they take one or more input arguments
|
||||||
|
which are used for the macro expansion.
|
||||||
|
They look like macro/function calls but use the special variable <tt>$</tt> prefix to the macro name.
|
||||||
|
Note that unlike normal macros, the expansion is not done by the preprocessor,
|
||||||
|
it is done during the SWIG parsing/compilation stages.
|
||||||
|
The following special variable macros are available across all language modules.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<H4><a name="Typemaps_special_macro_descriptor"></a>10.4.4.1 $descriptor(type)</H4>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This macro expands into the type descriptor structure for any C/C++ type specified in <tt>type</tt>.
|
||||||
|
It behaves like the <tt>$1_descriptor</tt> special variable described above except that the type to expand is
|
||||||
|
taken from the macro argument rather than inferred from the typemap type.
|
||||||
|
For example, <tt>$descriptor(std::vector<int> *)</tt> will expand into <tt>SWIGTYPE_p_std__vectorT_int_t</tt>.
|
||||||
|
This macro is mostly used in the scripting target languages and is demonstrated later in the <a href="#Typemaps_runtime_type_checker_usage">Run-time type checker usage</a> section.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<H4><a name="Typemaps_special_macro_typemap"></a>10.4.4.2 $typemap(method, typepattern)</H4>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This macro uses the <a href="#Typemaps_pattern_matching">pattern matching rules</a> described earlier to lookup and
|
||||||
|
then substitute the special variable macro with the code in the matched typemap.
|
||||||
|
The typemap to search for is specified by the arguments, where <tt>method</tt> is the typemap method name and
|
||||||
|
<tt>typepattern</tt> is a type pattern as per the <tt>%typemap</tt> specification in the <a href="#Typemaps_defining">Defining a typemap</a> section.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The special variables within the matched typemap are expanded into those for the matched typemap type,
|
||||||
|
not the typemap within which the macro is called.
|
||||||
|
In practice, there is little use for this macro in the scripting target languages.
|
||||||
|
It is mostly used in the target languages that are statically typed as a way to obtain the target language type given the C/C++ type and more commonly only when the C++ type is a template parameter.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The example below is for C# only and uses some typemap method names documented in the C# chapter, but it shows some of the possible syntax variations.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%typemap(cstype) unsigned long "uint"
|
||||||
|
%typemap(cstype) unsigned long bb "bool"
|
||||||
|
%typemap(cscode) BarClass %{
|
||||||
|
void foo($typemap(cstype, unsigned long aa) var1,
|
||||||
|
$typemap(cstype, unsigned long bb) var2,
|
||||||
|
$typemap(cstype, (unsigned long bb)) var3,
|
||||||
|
$typemap(cstype, unsigned long) var4)
|
||||||
|
{
|
||||||
|
// do something
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The result is the following expansion
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%typemap(cstype) unsigned long "uint"
|
||||||
|
%typemap(cstype) unsigned long bb "bool"
|
||||||
|
%typemap(cscode) BarClass %{
|
||||||
|
void foo(uint var1,
|
||||||
|
bool var2,
|
||||||
|
bool var3,
|
||||||
|
uint var4)
|
||||||
|
{
|
||||||
|
// do something
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
<H2><a name="Typemaps_nn25"></a>10.5 Common typemap methods</H2>
|
<H2><a name="Typemaps_nn25"></a>10.5 Common typemap methods</H2>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3295,7 +3381,7 @@ structures rather than creating new ones. These <tt>swig_module_info</tt>
|
||||||
structures are chained together in a circularly linked list.
|
structures are chained together in a circularly linked list.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H3><a name="Typemaps_nn46"></a>10.10.2 Usage</H3>
|
<H3><a name="Typemaps_runtime_type_checker_usage"></a>10.10.2 Usage</H3>
|
||||||
|
|
||||||
|
|
||||||
<p>This section covers how to use these functions from typemaps. To learn how to
|
<p>This section covers how to use these functions from typemaps. To learn how to
|
||||||
|
|
@ -3335,8 +3421,8 @@ type tables and improves efficiency.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Occasionally, you might need to write a typemap that needs to convert
|
Occasionally, you might need to write a typemap that needs to convert
|
||||||
pointers of other types. To handle this, a special macro substitution
|
pointers of other types. To handle this, the special variable macro
|
||||||
<tt>$descriptor(type)</tt> can be used to generate the SWIG type
|
<tt>$descriptor(type)</tt> covered earlier can be used to generate the SWIG type
|
||||||
descriptor name for any C datatype. For example:
|
descriptor name for any C datatype. For example:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
||||||
22
Examples/php/callback/Makefile
Normal file
22
Examples/php/callback/Makefile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
TOP = ../..
|
||||||
|
SWIG = $(TOP)/../preinst-swig
|
||||||
|
CXXSRCS = example.cxx
|
||||||
|
TARGET = example
|
||||||
|
INTERFACE = example.i
|
||||||
|
LIBS = -lm
|
||||||
|
SWIGOPT =
|
||||||
|
|
||||||
|
all::
|
||||||
|
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
|
||||||
|
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp
|
||||||
|
|
||||||
|
static::
|
||||||
|
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
|
||||||
|
SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static
|
||||||
|
|
||||||
|
clean::
|
||||||
|
$(MAKE) -f $(TOP)/Makefile php_clean
|
||||||
|
rm -f $(TARGET).php
|
||||||
|
|
||||||
|
check: all
|
||||||
|
$(MAKE) -f $(TOP)/Makefile php_run
|
||||||
4
Examples/php/callback/example.cxx
Normal file
4
Examples/php/callback/example.cxx
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* File : example.cxx */
|
||||||
|
|
||||||
|
#include "example.h"
|
||||||
|
|
||||||
22
Examples/php/callback/example.h
Normal file
22
Examples/php/callback/example.h
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* File : example.h */
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Callback {
|
||||||
|
public:
|
||||||
|
virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; }
|
||||||
|
virtual void run() { std::cout << "Callback::run()" << std::endl; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Caller {
|
||||||
|
private:
|
||||||
|
Callback *_callback;
|
||||||
|
public:
|
||||||
|
Caller(): _callback(0) {}
|
||||||
|
~Caller() { delCallback(); }
|
||||||
|
void delCallback() { delete _callback; _callback = 0; }
|
||||||
|
void setCallback(Callback *cb) { delCallback(); _callback = cb; }
|
||||||
|
void call() { if (_callback) _callback->run(); }
|
||||||
|
};
|
||||||
|
|
||||||
13
Examples/php/callback/example.i
Normal file
13
Examples/php/callback/example.i
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
/* File : example.i */
|
||||||
|
%module(directors="1") example
|
||||||
|
%{
|
||||||
|
#include "example.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "std_string.i"
|
||||||
|
|
||||||
|
/* turn on director wrapping Callback */
|
||||||
|
%feature("director") Callback;
|
||||||
|
|
||||||
|
%include "example.h"
|
||||||
|
|
||||||
19
Examples/php/callback/index.html
Normal file
19
Examples/php/callback/index.html
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>SWIG:Examples:php:callback</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#ffffff">
|
||||||
|
|
||||||
|
|
||||||
|
<tt>SWIG/Examples/php/callback/</tt>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<H2>Implementing C++ callbacks in PHP</H2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This example illustrates how to use directors to implement C++ callbacks in PHP.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
47
Examples/php/callback/runme.php
Normal file
47
Examples/php/callback/runme.php
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
# This file illustrates the cross language polymorphism using directors.
|
||||||
|
|
||||||
|
require("example.php");
|
||||||
|
|
||||||
|
# Class, which overwrites Callback::run().
|
||||||
|
|
||||||
|
class PhpCallback extends Callback {
|
||||||
|
function run() {
|
||||||
|
print "PhpCallback.run()\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create an Caller instance
|
||||||
|
|
||||||
|
$caller = new Caller();
|
||||||
|
|
||||||
|
# Add a simple C++ callback (caller owns the callback, so
|
||||||
|
# we disown it first by clearing the .thisown flag).
|
||||||
|
|
||||||
|
print "Adding and calling a normal C++ callback\n";
|
||||||
|
print "----------------------------------------\n";
|
||||||
|
|
||||||
|
$callback = new Callback();
|
||||||
|
$callback->thisown = 0;
|
||||||
|
$caller->setCallback($callback);
|
||||||
|
$caller->call();
|
||||||
|
$caller->delCallback();
|
||||||
|
|
||||||
|
print "\n";
|
||||||
|
print "Adding and calling a PHP callback\n";
|
||||||
|
print "------------------------------------\n";
|
||||||
|
|
||||||
|
# Add a PHP callback.
|
||||||
|
|
||||||
|
$callback = new PhpCallback();
|
||||||
|
$callback->thisown = 0;
|
||||||
|
$caller->setCallback($callback);
|
||||||
|
$caller->call();
|
||||||
|
$caller->delCallback();
|
||||||
|
|
||||||
|
# All done.
|
||||||
|
|
||||||
|
print "php exit\n";
|
||||||
|
|
||||||
|
?>
|
||||||
22
Examples/php/extend/Makefile
Normal file
22
Examples/php/extend/Makefile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
TOP = ../..
|
||||||
|
SWIG = $(TOP)/../preinst-swig
|
||||||
|
CXXSRCS = example.cxx
|
||||||
|
TARGET = example
|
||||||
|
INTERFACE = example.i
|
||||||
|
LIBS = -lm
|
||||||
|
SWIGOPT =
|
||||||
|
|
||||||
|
all::
|
||||||
|
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
|
||||||
|
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp
|
||||||
|
|
||||||
|
static::
|
||||||
|
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
|
||||||
|
SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static
|
||||||
|
|
||||||
|
clean::
|
||||||
|
$(MAKE) -f $(TOP)/Makefile php_clean
|
||||||
|
rm -f $(TARGET).php
|
||||||
|
|
||||||
|
check: all
|
||||||
|
$(MAKE) -f $(TOP)/Makefile php_run
|
||||||
4
Examples/php/extend/example.cxx
Normal file
4
Examples/php/extend/example.cxx
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* File : example.cxx */
|
||||||
|
|
||||||
|
#include "example.h"
|
||||||
|
|
||||||
56
Examples/php/extend/example.h
Normal file
56
Examples/php/extend/example.h
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* File : example.h */
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
class Employee {
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
public:
|
||||||
|
Employee(const char* n): name(n) {}
|
||||||
|
virtual std::string getTitle() { return getPosition() + " " + getName(); }
|
||||||
|
virtual std::string getName() { return name; }
|
||||||
|
virtual std::string getPosition() const { return "Employee"; }
|
||||||
|
virtual ~Employee() { printf("~Employee() @ %p\n", this); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Manager: public Employee {
|
||||||
|
public:
|
||||||
|
Manager(const char* n): Employee(n) {}
|
||||||
|
virtual std::string getPosition() const { return "Manager"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class EmployeeList {
|
||||||
|
std::vector<Employee*> list;
|
||||||
|
public:
|
||||||
|
EmployeeList() {
|
||||||
|
list.push_back(new Employee("Bob"));
|
||||||
|
list.push_back(new Employee("Jane"));
|
||||||
|
list.push_back(new Manager("Ted"));
|
||||||
|
}
|
||||||
|
void addEmployee(Employee *p) {
|
||||||
|
list.push_back(p);
|
||||||
|
std::cout << "New employee added. Current employees are:" << std::endl;
|
||||||
|
std::vector<Employee*>::iterator i;
|
||||||
|
for (i=list.begin(); i!=list.end(); i++) {
|
||||||
|
std::cout << " " << (*i)->getTitle() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const Employee *get_item(int i) {
|
||||||
|
return list[i];
|
||||||
|
}
|
||||||
|
~EmployeeList() {
|
||||||
|
std::vector<Employee*>::iterator i;
|
||||||
|
std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl;
|
||||||
|
for (i=list.begin(); i!=list.end(); i++) {
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
std::cout << "~EmployeeList empty." << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
15
Examples/php/extend/example.i
Normal file
15
Examples/php/extend/example.i
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* File : example.i */
|
||||||
|
%module(directors="1") example
|
||||||
|
%{
|
||||||
|
#include "example.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "std_vector.i"
|
||||||
|
%include "std_string.i"
|
||||||
|
|
||||||
|
/* turn on director wrapping for Manager */
|
||||||
|
%feature("director") Employee;
|
||||||
|
%feature("director") Manager;
|
||||||
|
|
||||||
|
%include "example.h"
|
||||||
|
|
||||||
19
Examples/php/extend/index.html
Normal file
19
Examples/php/extend/index.html
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>SWIG:Examples:php:extend</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#ffffff">
|
||||||
|
|
||||||
|
|
||||||
|
<tt>SWIG/Examples/php/extend/</tt>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<H2>Extending a simple C++ class in PHP</H2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This example illustrates the extending of a C++ class with cross language polymorphism.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
76
Examples/php/extend/runme.php
Normal file
76
Examples/php/extend/runme.php
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
# This file illustrates the cross language polymorphism using directors.
|
||||||
|
|
||||||
|
require("example.php");
|
||||||
|
|
||||||
|
# CEO class, which overrides Employee::getPosition().
|
||||||
|
|
||||||
|
class CEO extends Manager {
|
||||||
|
function getPosition() {
|
||||||
|
return "CEO";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create an instance of our employee extension class, CEO. The calls to
|
||||||
|
# getName() and getPosition() are standard, the call to getTitle() uses
|
||||||
|
# the director wrappers to call CEO.getPosition.
|
||||||
|
|
||||||
|
$e = new CEO("Alice");
|
||||||
|
print $e->getName() . " is a " . $e->getPosition() . "\n";
|
||||||
|
printf("Just call her \"%s\"\n", $e->getTitle());
|
||||||
|
print "----------------------\n";
|
||||||
|
|
||||||
|
# Create a new EmployeeList instance. This class does not have a C++
|
||||||
|
# director wrapper, but can be used freely with other classes that do.
|
||||||
|
|
||||||
|
$list = new EmployeeList();
|
||||||
|
|
||||||
|
# EmployeeList owns its items, so we must surrender ownership of objects
|
||||||
|
# we add. This involves first clearing the ->disown member to tell the
|
||||||
|
# C++ director to start reference counting.
|
||||||
|
|
||||||
|
$e->thisown = 0;
|
||||||
|
$list->addEmployee($e);
|
||||||
|
print "----------------------\n";
|
||||||
|
|
||||||
|
# Now we access the first four items in list (three are C++ objects that
|
||||||
|
# EmployeeList's constructor adds, the last is our CEO). The virtual
|
||||||
|
# methods of all these instances are treated the same. For items 0, 1, and
|
||||||
|
# 2, both all methods resolve in C++. For item 3, our CEO, getTitle calls
|
||||||
|
# getPosition which resolves in PHP. The call to getPosition is
|
||||||
|
# slightly different, however, from the e.getPosition() call above, since
|
||||||
|
# now the object reference has been "laundered" by passing through
|
||||||
|
# EmployeeList as an Employee*. Previously, PHP resolved the call
|
||||||
|
# immediately in CEO, but now PHP thinks the object is an instance of
|
||||||
|
# class Employee (actually EmployeePtr). So the call passes through the
|
||||||
|
# Employee proxy class and on to the C wrappers and C++ director,
|
||||||
|
# eventually ending up back at the CEO implementation of getPosition().
|
||||||
|
# The call to getTitle() for item 3 runs the C++ Employee::getTitle()
|
||||||
|
# method, which in turn calls getPosition(). This virtual method call
|
||||||
|
# passes down through the C++ director class to the PHP implementation
|
||||||
|
# in CEO. All this routing takes place transparently.
|
||||||
|
|
||||||
|
print "(position, title) for items 0-3:\n";
|
||||||
|
|
||||||
|
printf(" %s, \"%s\"\n", $list->get_item(0)->getPosition(), $list->get_item(0)->getTitle());
|
||||||
|
printf(" %s, \"%s\"\n", $list->get_item(1)->getPosition(), $list->get_item(1)->getTitle());
|
||||||
|
printf(" %s, \"%s\"\n", $list->get_item(2)->getPosition(), $list->get_item(2)->getTitle());
|
||||||
|
printf(" %s, \"%s\"\n", $list->get_item(3)->getPosition(), $list->get_item(3)->getTitle());
|
||||||
|
print "----------------------\n";
|
||||||
|
|
||||||
|
# Time to delete the EmployeeList, which will delete all the Employee*
|
||||||
|
# items it contains. The last item is our CEO, which gets destroyed as its
|
||||||
|
# reference count goes to zero. The PHP destructor runs, and is still
|
||||||
|
# able to call the getName() method since the underlying C++ object still
|
||||||
|
# exists. After this destructor runs the remaining C++ destructors run as
|
||||||
|
# usual to destroy the object.
|
||||||
|
|
||||||
|
unset($list);
|
||||||
|
print "----------------------\n";
|
||||||
|
|
||||||
|
# All done.
|
||||||
|
|
||||||
|
print "php exit\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
/* File : example.h */
|
/* File : example.h */
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
class Callback {
|
class Callback {
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,7 @@ CPP_TEST_CASES += \
|
||||||
smart_pointer_templatevariables \
|
smart_pointer_templatevariables \
|
||||||
smart_pointer_typedef \
|
smart_pointer_typedef \
|
||||||
special_variables \
|
special_variables \
|
||||||
|
special_variable_macros \
|
||||||
static_array_member \
|
static_array_member \
|
||||||
static_const_member \
|
static_const_member \
|
||||||
static_const_member_2 \
|
static_const_member_2 \
|
||||||
|
|
|
||||||
20
Examples/test-suite/csharp/special_variable_macros_runme.cs
Normal file
20
Examples/test-suite/csharp/special_variable_macros_runme.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using special_variable_macrosNamespace;
|
||||||
|
|
||||||
|
public class runme {
|
||||||
|
static void Main() {
|
||||||
|
Name name = new Name();
|
||||||
|
if (special_variable_macros.testFred(name) != "none")
|
||||||
|
throw new Exception("test failed");
|
||||||
|
if (special_variable_macros.testJack(name) != "$specialname")
|
||||||
|
throw new Exception("test failed");
|
||||||
|
if (special_variable_macros.testJill(name) != "jilly")
|
||||||
|
throw new Exception("test failed");
|
||||||
|
if (special_variable_macros.testMary(name) != "SWIGTYPE_p_NameWrap")
|
||||||
|
throw new Exception("test failed");
|
||||||
|
if (special_variable_macros.testJim(name) != "multiname num")
|
||||||
|
throw new Exception("test failed");
|
||||||
|
NewName newName = NewName.factory("factoryname");
|
||||||
|
name = newName.getStoredName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,7 +25,10 @@
|
||||||
"$csclassname.getCPtr(d$csinput)"
|
"$csclassname.getCPtr(d$csinput)"
|
||||||
|
|
||||||
// post only in csin typemap
|
// post only in csin typemap
|
||||||
%typemap(csin, post=" int size = $csinput.Count;\n for (int i=0; i<size; ++i) {\n $csinput[i] /= 100;\n }") std::vector<double> &vpost
|
%typemap(csin, post=" int size = $csinput.Count;\n"
|
||||||
|
" for (int i=0; i<size; ++i) {\n"
|
||||||
|
" $csinput[i] /= 100;\n"
|
||||||
|
" }") std::vector<double> &vpost
|
||||||
"$csclassname.getCPtr($csinput)"
|
"$csclassname.getCPtr($csinput)"
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@
|
||||||
%feature("director") Foo;
|
%feature("director") Foo;
|
||||||
|
|
||||||
%newobject Foo::cloner();
|
%newobject Foo::cloner();
|
||||||
|
%newobject Foo::get_class();
|
||||||
%newobject Bar::cloner();
|
%newobject Bar::cloner();
|
||||||
|
%newobject Bar::get_class();
|
||||||
|
|
||||||
|
|
||||||
%inline {
|
%inline {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,13 @@
|
||||||
|
|
||||||
%newobject *::create();
|
%newobject *::create();
|
||||||
|
|
||||||
|
#ifdef SWIGPHP
|
||||||
|
// TODO: Currently we do not track the dynamic type of returned objects
|
||||||
|
// in PHP, so we need the factory helper.
|
||||||
|
%include factory.i
|
||||||
|
%factory(Foo *Bar::create, Bar);
|
||||||
|
#endif
|
||||||
|
|
||||||
%rename(a) Bar::hello;
|
%rename(a) Bar::hello;
|
||||||
%rename(s) Foo::p;
|
%rename(s) Foo::p;
|
||||||
%rename(q) Foo::r;
|
%rename(q) Foo::r;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@
|
||||||
%feature("director") Foo;
|
%feature("director") Foo;
|
||||||
|
|
||||||
%feature("director:except") {
|
%feature("director:except") {
|
||||||
|
#ifndef SWIGPHP
|
||||||
if ($error != NULL) {
|
if ($error != NULL) {
|
||||||
|
#else
|
||||||
|
if ($error == FAILURE) {
|
||||||
|
#endif
|
||||||
throw Swig::DirectorMethodException();
|
throw Swig::DirectorMethodException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
%module(directors="1",dirprot="1") director_using
|
%module(directors="1",dirprot="1") director_using
|
||||||
|
|
||||||
|
%warnfilter(SWIGWARN_PHP_PUBLIC_BASE) FooBar;
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
||||||
30
Examples/test-suite/java/special_variable_macros_runme.java
Normal file
30
Examples/test-suite/java/special_variable_macros_runme.java
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
import special_variable_macros.*;
|
||||||
|
|
||||||
|
public class special_variable_macros_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("special_variable_macros");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
Name name = new Name();
|
||||||
|
if (!special_variable_macros.testFred(name).equals("none"))
|
||||||
|
throw new RuntimeException("test failed");
|
||||||
|
if (!special_variable_macros.testJack(name).equals("$specialname"))
|
||||||
|
throw new RuntimeException("test failed");
|
||||||
|
if (!special_variable_macros.testJill(name).equals("jilly"))
|
||||||
|
throw new RuntimeException("test failed");
|
||||||
|
if (!special_variable_macros.testMary(name).equals("SWIGTYPE_p_NameWrap"))
|
||||||
|
throw new RuntimeException("test failed");
|
||||||
|
if (!special_variable_macros.testJim(name).equals("multiname num"))
|
||||||
|
throw new RuntimeException("test failed");
|
||||||
|
NewName newName = NewName.factory("factoryname");
|
||||||
|
name = newName.getStoredName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
%newobject Geometry::clone;
|
%newobject Geometry::clone;
|
||||||
%factory(Geometry *Geometry::create, Point, Circle);
|
%factory(Geometry *Geometry::create, Point, Circle);
|
||||||
%factory(Geometry *Geometry::clone, Point, Circle);
|
%factory(Geometry *Geometry::clone, Point, Circle);
|
||||||
|
#ifdef SWIGPHP
|
||||||
|
%rename(clone_) clone;
|
||||||
|
#endif
|
||||||
%factory(Geometry *Point::clone, Point, Circle);
|
%factory(Geometry *Point::clone, Point, Circle);
|
||||||
%factory(Geometry *Circle::clone, Point, Circle);
|
%factory(Geometry *Circle::clone, Point, Circle);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ namespace std
|
||||||
{
|
{
|
||||||
typedef complex None;
|
typedef complex None;
|
||||||
|
|
||||||
|
#ifndef SWIGPHP // clone() *is* an invalid method name in PHP.
|
||||||
A* clone(int) { return NULL; }
|
A* clone(int) { return NULL; }
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual ~A() {}
|
virtual ~A() {}
|
||||||
virtual int func() = 0;
|
virtual int func() = 0;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
%rename(PlusPlusPostfix) operator++(int);
|
%rename(PlusPlusPostfix) operator++(int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
@ -56,7 +55,7 @@ public:
|
||||||
|
|
||||||
Op& operator++() {k++; return *this;}
|
Op& operator++() {k++; return *this;}
|
||||||
|
|
||||||
void Print() {std::cerr << k << std::endl;}
|
void PrintK() {std::cerr << k << std::endl;}
|
||||||
|
|
||||||
int k;
|
int k;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
#CPP_TEST_CASES += \
|
CPP_TEST_CASES += \
|
||||||
# php_namewarn_rename \
|
php_namewarn_rename \
|
||||||
|
|
||||||
include $(srcdir)/../common.mk
|
include $(srcdir)/../common.mk
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ include $(srcdir)/../common.mk
|
||||||
TARGETPREFIX =# Should be php_ for Windows, empty otherwise
|
TARGETPREFIX =# Should be php_ for Windows, empty otherwise
|
||||||
|
|
||||||
# Custom tests - tests with additional commandline options
|
# Custom tests - tests with additional commandline options
|
||||||
# none!
|
prefix.cpptest: SWIGOPT += -prefix Project
|
||||||
|
|
||||||
# write out tests without a _runme.php
|
# write out tests without a _runme.php
|
||||||
missingcpptests:
|
missingcpptests:
|
||||||
|
|
|
||||||
62
Examples/test-suite/php/director_abstract_runme.php
Normal file
62
Examples/test-suite/php/director_abstract_runme.php
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_abstract.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_ping,foo_pong,example0_getxsize,example0_color,example0_get_color,example1_getxsize,example1_color,example1_get_color,example2_getxsize,example2_color,example2_get_color,example4_getxsize,example4_color,example4_get_color,example3_i_color,example3_i_get_color,g,a_f));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(director_abstract,Foo,Example0,Example1,Example2,Example4,Example3_i,A));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyFoo extends Foo {
|
||||||
|
function ping() {
|
||||||
|
return "MyFoo::ping()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new MyFoo();
|
||||||
|
|
||||||
|
check::equal($a->ping(), "MyFoo::ping()", "MyFoo::ping failed");
|
||||||
|
|
||||||
|
check::equal($a->pong(), "Foo::pong();MyFoo::ping()", "MyFoo::pong failed");
|
||||||
|
|
||||||
|
class MyExample1 extends Example1 {
|
||||||
|
function Color($r, $g, $b) {
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyExample2 extends Example1 {
|
||||||
|
function Color($r, $g, $b) {
|
||||||
|
return $g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyExample3 extends Example1 {
|
||||||
|
function Color($r, $g, $b) {
|
||||||
|
return $b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$me1 = new MyExample1();
|
||||||
|
check::equal($me1->Color(1, 2, 3), 1, "Example1_get_color failed");
|
||||||
|
|
||||||
|
$me2 = new MyExample2(1, 2);
|
||||||
|
check::equal($me2->Color(1, 2, 3), 2, "Example2_get_color failed");
|
||||||
|
|
||||||
|
$me3 = new MyExample3();
|
||||||
|
check::equal($me3->Color(1, 2, 3), 3, "Example3_get_color failed");
|
||||||
|
|
||||||
|
$class = new ReflectionClass('Example1');
|
||||||
|
check::equal($class->isAbstract(), true, "Example1 abstractness failed");
|
||||||
|
|
||||||
|
$class = new ReflectionClass('Example2');
|
||||||
|
check::equal($class->isAbstract(), true, "Example2 abstractness failed");
|
||||||
|
|
||||||
|
$class = new ReflectionClass('Example3_i');
|
||||||
|
check::equal($class->isAbstract(), true, "Example3_i abstractness failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
58
Examples/test-suite/php/director_basic_runme.php
Normal file
58
Examples/test-suite/php/director_basic_runme.php
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_basic.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_ping,foo_pong,foo_get_self,a_f,a_rg,a1_ff,myclass_method,myclass_vmethod,myclass_pmethod,myclass_cmethod,myclass_get_self,myclass_call_pmethod,myclasst_i_method));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Foo,A,A1,Bar,MyClass,MyClassT_i));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array(bar_x));
|
||||||
|
|
||||||
|
class PhpFoo extends Foo {
|
||||||
|
function ping() {
|
||||||
|
return "PhpFoo::ping()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new PhpFoo();
|
||||||
|
|
||||||
|
check::equal($a->ping(), "PhpFoo::ping()", "ping failed");
|
||||||
|
|
||||||
|
check::equal($a->pong(), "Foo::pong();PhpFoo::ping()", "pong failed");
|
||||||
|
|
||||||
|
$b = new Foo();
|
||||||
|
|
||||||
|
check::equal($b->ping(), "Foo::ping()", "ping failed");
|
||||||
|
|
||||||
|
check::equal($b->pong(), "Foo::pong();Foo::ping()", "pong failed");
|
||||||
|
|
||||||
|
$a = new A1(1);
|
||||||
|
|
||||||
|
check::equal($a->rg(2), 2, "rg failed");
|
||||||
|
|
||||||
|
class PhpClass extends MyClass {
|
||||||
|
function vmethod($b) {
|
||||||
|
$b->x = $b->x + 31;
|
||||||
|
return $b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new Bar(3);
|
||||||
|
$d = new MyClass();
|
||||||
|
$c = new PhpClass();
|
||||||
|
|
||||||
|
$cc = MyClass::get_self($c);
|
||||||
|
$dd = MyClass::get_self($d);
|
||||||
|
|
||||||
|
$bc = $cc->cmethod($b);
|
||||||
|
$bd = $dd->cmethod($b);
|
||||||
|
|
||||||
|
$cc->method($b);
|
||||||
|
|
||||||
|
check::equal($bc->x, 34, "bc failed");
|
||||||
|
check::equal($bd->x, 16, "bd failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
150
Examples/test-suite/php/director_classic_runme.php
Normal file
150
Examples/test-suite/php/director_classic_runme.php
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_classic.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(being_id,person_id,child_id,grandchild_id,caller_delcallback,caller_setcallback,caller_resetcallback,caller_call,caller_baseclass));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Being,Person,Child,GrandChild,OrphanPerson,OrphanChild,Caller));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class TargetLangPerson extends Person {
|
||||||
|
function id() {
|
||||||
|
$identifier = "TargetLangPerson";
|
||||||
|
return $identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetLangChild extends Child {
|
||||||
|
function id() {
|
||||||
|
$identifier = "TargetLangChild";
|
||||||
|
return $identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetLangGrandChild extends GrandChild {
|
||||||
|
function id() {
|
||||||
|
$identifier = "TargetLangGrandChild";
|
||||||
|
return $identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Semis - don't override id() in target language
|
||||||
|
class TargetLangSemiPerson extends Person {
|
||||||
|
# No id() override
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetLangSemiChild extends Child {
|
||||||
|
# No id() override
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetLangSemiGrandChild extends GrandChild {
|
||||||
|
# No id() override
|
||||||
|
}
|
||||||
|
|
||||||
|
# Orphans - don't override id() in C++
|
||||||
|
class TargetLangOrphanPerson extends OrphanPerson {
|
||||||
|
function id() {
|
||||||
|
$identifier = "TargetLangOrphanPerson";
|
||||||
|
return $identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetLangOrphanChild extends OrphanChild {
|
||||||
|
function id() {
|
||||||
|
$identifier = "TargetLangOrphanChild";
|
||||||
|
return $identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mycheck($person, $expected) {
|
||||||
|
$debug = 0;
|
||||||
|
# Normal target language polymorphic call
|
||||||
|
$ret = $person->id();
|
||||||
|
if ($debug)
|
||||||
|
print $ret . "\n";
|
||||||
|
check::equal($ret, $expected, "#1 failed");
|
||||||
|
|
||||||
|
# Polymorphic call from C++
|
||||||
|
$caller = new Caller();
|
||||||
|
$caller->setCallback($person);
|
||||||
|
$ret = $caller->call();
|
||||||
|
if ($debug)
|
||||||
|
print $ret . "\n";
|
||||||
|
check::equal($ret, $expected, "#2 failed");
|
||||||
|
|
||||||
|
# Polymorphic call of object created in target language and passed to
|
||||||
|
# C++ and back again
|
||||||
|
$baseclass = $caller->baseClass();
|
||||||
|
$ret = $baseclass->id();
|
||||||
|
if ($debug)
|
||||||
|
print $ret . "\n";
|
||||||
|
# TODO: Currently we do not track the dynamic type of returned
|
||||||
|
# objects, so in case it's possible that the dynamic type is not equal
|
||||||
|
# to the static type, we skip this check.
|
||||||
|
if (get_parent_class($person) === false)
|
||||||
|
check::equal($ret, $expected, "#3 failed");
|
||||||
|
|
||||||
|
$caller->resetCallback();
|
||||||
|
if ($debug)
|
||||||
|
print "----------------------------------------\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$person = new Person();
|
||||||
|
mycheck($person, "Person");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new Child();
|
||||||
|
mycheck($person, "Child");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new GrandChild();
|
||||||
|
mycheck($person, "GrandChild");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new TargetLangPerson();
|
||||||
|
mycheck($person, "TargetLangPerson");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new TargetLangChild();
|
||||||
|
mycheck($person, "TargetLangChild");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new TargetLangGrandChild();
|
||||||
|
mycheck($person, "TargetLangGrandChild");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
# Semis - don't override id() in target language
|
||||||
|
$person = new TargetLangSemiPerson();
|
||||||
|
mycheck($person, "Person");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new TargetLangSemiChild();
|
||||||
|
mycheck($person, "Child");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new TargetLangSemiGrandChild();
|
||||||
|
mycheck($person, "GrandChild");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
# Orphans - don't override id() in C++
|
||||||
|
$person = new OrphanPerson();
|
||||||
|
mycheck($person, "Person");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new OrphanChild();
|
||||||
|
mycheck($person, "Child");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new TargetLangOrphanPerson();
|
||||||
|
mycheck($person, "TargetLangOrphanPerson");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
$person = new TargetLangOrphanChild();
|
||||||
|
mycheck($person, "TargetLangOrphanChild");
|
||||||
|
unset($person);
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
20
Examples/test-suite/php/director_default_runme.php
Normal file
20
Examples/test-suite/php/director_default_runme.php
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_default.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_msg,foo_getmsg,bar_msg,bar_getmsg,defaultsbase_defaultargs,defaultsderived_defaultargs));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Foo,Bar,DefaultsBase,DefaultsDerived));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
$f = new Foo();
|
||||||
|
$f = new Foo(1);
|
||||||
|
|
||||||
|
$f = new Bar();
|
||||||
|
$f = new Bar(1);
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
55
Examples/test-suite/php/director_detect_runme.php
Normal file
55
Examples/test-suite/php/director_detect_runme.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_detect.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_cloner,foo_get_value,foo_get_class,foo_just_do_it,bar_baseclass,bar_cloner,bar_get_value,bar_get_class,bar_just_do_it));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(A,Foo,Bar));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyBar extends Bar {
|
||||||
|
function __construct($val = 2) {
|
||||||
|
parent::__construct();
|
||||||
|
$this->val = $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_value() {
|
||||||
|
$this->val = $this->val + 1;
|
||||||
|
return $this->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_class() {
|
||||||
|
$this->val = $this->val + 1;
|
||||||
|
return new A();
|
||||||
|
}
|
||||||
|
|
||||||
|
function just_do_it() {
|
||||||
|
$this->val = $this->val + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clone is a reserved keyword */
|
||||||
|
function clone_() {
|
||||||
|
return new MyBar($this->val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new MyBar();
|
||||||
|
|
||||||
|
$f = $b->baseclass();
|
||||||
|
|
||||||
|
$v = $f->get_value();
|
||||||
|
$a = $f->get_class();
|
||||||
|
$f->just_do_it();
|
||||||
|
|
||||||
|
$c = $b->clone_();
|
||||||
|
$vc = $c->get_value();
|
||||||
|
|
||||||
|
check::equal($v, 3, "f: Bad virtual detection");
|
||||||
|
check::equal($b->val, 5, "b: Bad virtual detection");
|
||||||
|
check::equal($vc, 6, "c: Bad virtual detection");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
25
Examples/test-suite/php/director_enum_runme.php
Normal file
25
Examples/test-suite/php/director_enum_runme.php
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_enum.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_say_hello,foo_say_hi,foo_say_bye,foo_say_hi_ref,foo_ping,foo_ping_ref,foo_ping_member_enum,a_f,a2_f));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(director_enum,Foo,A,B,A2,B2));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyFoo extends Foo {
|
||||||
|
function say_hi($val) {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new Foo();
|
||||||
|
$a = new MyFoo();
|
||||||
|
|
||||||
|
check::equal($a->say_hi(director_enum::hello), $b->say_hello(director_enum::hi), "say failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
78
Examples/test-suite/php/director_exception_runme.php
Normal file
78
Examples/test-suite/php/director_exception_runme.php
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_exception.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_ping,foo_pong,launder,bar_ping,bar_pong,bar_pang));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(director_exception,Foo,Exception1,Exception2,Base,Bar));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyException extends Exception {
|
||||||
|
function __construct($a, $b) {
|
||||||
|
$this->msg = $a . $b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyFoo extends Foo {
|
||||||
|
function ping() {
|
||||||
|
throw new Exception("MyFoo::ping() EXCEPTION");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyFoo2 extends Foo {
|
||||||
|
function ping() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyFoo3 extends Foo {
|
||||||
|
function ping() {
|
||||||
|
throw new MyException("foo", "bar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check that the Exception raised by MyFoo.ping() is returned by
|
||||||
|
# MyFoo.pong().
|
||||||
|
$ok = 0;
|
||||||
|
$a = new MyFoo();
|
||||||
|
# TODO: Currently we do not track the dynamic type of returned
|
||||||
|
# objects, so we skip the launder() call.
|
||||||
|
#$b = director_exception::launder($a);
|
||||||
|
$b = $a;
|
||||||
|
try {
|
||||||
|
$b->pong();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$ok = 1;
|
||||||
|
check::equal($e->getMessage(), "MyFoo::ping() EXCEPTION", "Unexpected error message #1");
|
||||||
|
}
|
||||||
|
check::equal($ok, 1, "Got no exception while expected one #1");
|
||||||
|
|
||||||
|
# Check that the director can return an exception which requires two
|
||||||
|
# arguments to the constructor, without mangling it.
|
||||||
|
$ok = 0;
|
||||||
|
$a = new MyFoo3();
|
||||||
|
#$b = director_exception::launder($a);
|
||||||
|
$b = $a;
|
||||||
|
try {
|
||||||
|
$b->pong();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$ok = 1;
|
||||||
|
check::equal($e->msg, "foobar", "Unexpected error message #2");
|
||||||
|
}
|
||||||
|
check::equal($ok, 1, "Got no exception while expected one #2");
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw new Exception2();
|
||||||
|
} catch (Exception2 $e2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw new Exception1();
|
||||||
|
} catch (Exception1 $e1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
29
Examples/test-suite/php/director_extend_runme.php
Normal file
29
Examples/test-suite/php/director_extend_runme.php
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_extend.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(spobject_getfoobar,spobject_dummy,spobject_exceptionmethod));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(SpObject));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyObject extends SpObject{
|
||||||
|
function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFoo() {
|
||||||
|
return 123;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$m = new MyObject();
|
||||||
|
check::equal($m->dummy(), 666, "1st call");
|
||||||
|
check::equal($m->dummy(), 666, "2st call"); // Locked system
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
61
Examples/test-suite/php/director_finalizer_runme.php
Normal file
61
Examples/test-suite/php/director_finalizer_runme.php
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_finalizer.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_orstatus,deletefoo,getstatus,launder,resetstatus));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(director_finalizer,Foo));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyFoo extends Foo {
|
||||||
|
function __destruct() {
|
||||||
|
$this->orStatus(2);
|
||||||
|
if (method_exists(parent, "__destruct")) {
|
||||||
|
parent::__destruct();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetStatus();
|
||||||
|
|
||||||
|
$a = new MyFoo();
|
||||||
|
unset($a);
|
||||||
|
|
||||||
|
check::equal(getStatus(), 3, "getStatus() failed #1");
|
||||||
|
|
||||||
|
resetStatus();
|
||||||
|
|
||||||
|
$a = new MyFoo();
|
||||||
|
launder($a);
|
||||||
|
|
||||||
|
check::equal(getStatus(), 0, "getStatus() failed #2");
|
||||||
|
|
||||||
|
unset($a);
|
||||||
|
|
||||||
|
check::equal(getStatus(), 3, "getStatus() failed #3");
|
||||||
|
|
||||||
|
resetStatus();
|
||||||
|
|
||||||
|
$a = new MyFoo();
|
||||||
|
$a->thisown = 0;
|
||||||
|
deleteFoo($a);
|
||||||
|
unset($a);
|
||||||
|
|
||||||
|
check::equal(getStatus(), 3, "getStatus() failed #4");
|
||||||
|
|
||||||
|
resetStatus();
|
||||||
|
|
||||||
|
$a = new MyFoo();
|
||||||
|
$a->thisown = 0;
|
||||||
|
deleteFoo(launder($a));
|
||||||
|
unset($a);
|
||||||
|
|
||||||
|
check::equal(getStatus(), 3, "getStatus() failed #5");
|
||||||
|
|
||||||
|
resetStatus();
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
19
Examples/test-suite/php/director_frob_runme.php
Normal file
19
Examples/test-suite/php/director_frob_runme.php
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_frob.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(alpha_abs_method,bravo_abs_method,charlie_abs_method,ops_opint,ops_opintstarstarconst,ops_opintamp,ops_opintstar,ops_opconstintintstar,prims_ull,prims_callull,corecallbacks_on3dengineredrawn,corecallbacks_on3dengineredrawn2));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Alpha,Bravo,Charlie,Delta,Ops,Prims,corePoint3d,coreCallbacks_On3dEngineRedrawnData,coreCallbacksOn3dEngineRedrawnData,coreCallbacks));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array(corecallbacks_on3dengineredrawndata__eye,corecallbacks_on3dengineredrawndata__at,corecallbackson3dengineredrawndata__eye,corecallbackson3dengineredrawndata__at));
|
||||||
|
|
||||||
|
$foo = new Bravo();
|
||||||
|
$s = $foo->abs_method();
|
||||||
|
|
||||||
|
check::equal($s, "Bravo::abs_method()", "s failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
75
Examples/test-suite/php/director_nested_runme.php
Normal file
75
Examples/test-suite/php/director_nested_runme.php
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
// Sample test file
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_nested.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_int_advance,foo_int_do_advance,bar_step,bar_do_advance,bar_do_step,foobar_int_get_value,foobar_int_get_name,foobar_int_name,foobar_int_get_self,foobar_int_do_advance,foobar_int_do_step));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Foo_int,Bar,FooBar_int));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class A extends FooBar_int {
|
||||||
|
function do_step() {
|
||||||
|
return "A::do_step;";
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_value() {
|
||||||
|
return "A::get_value";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
check::equal($a->step(), "Bar::step;Foo::advance;Bar::do_advance;A::do_step;", "Bad A virtual resolution");
|
||||||
|
|
||||||
|
class B extends FooBar_int {
|
||||||
|
function do_advance() {
|
||||||
|
return "B::do_advance;" . $this->do_step();
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_step() {
|
||||||
|
return "B::do_step;";
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_value() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new B();
|
||||||
|
|
||||||
|
check::equal($b->step(), "Bar::step;Foo::advance;B::do_advance;B::do_step;", "Bad B virtual resolution");
|
||||||
|
|
||||||
|
class C extends FooBar_int {
|
||||||
|
function do_advance() {
|
||||||
|
return "C::do_advance;" . parent::do_advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_step() {
|
||||||
|
return "C::do_step;";
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_value() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_name() {
|
||||||
|
return parent::get_name() . " hello";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$cc = new C();
|
||||||
|
# TODO: Currently we do not track the dynamic type of returned
|
||||||
|
# objects, so we skip the get_self() call.
|
||||||
|
#$c = Foobar_int::get_self($cc);
|
||||||
|
$c = $cc;
|
||||||
|
$c->advance();
|
||||||
|
|
||||||
|
check::equal($c->get_name(), "FooBar::get_name hello", "get_name failed");
|
||||||
|
|
||||||
|
check::equal($c->name(), "FooBar::get_name hello", "name failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
53
Examples/test-suite/php/director_profile_runme.php
Normal file
53
Examples/test-suite/php/director_profile_runme.php
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_profile.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(b_fn,b_vfi,b_fi,b_fj,b_fk,b_fl,b_get_self,b_vfs,b_fs));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(A,B));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyB extends B {
|
||||||
|
function vfi($a) {
|
||||||
|
return $a+3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
$myb = new MyB();
|
||||||
|
$b = B::get_self($myb);
|
||||||
|
|
||||||
|
$i = 50000;
|
||||||
|
$a = 1;
|
||||||
|
|
||||||
|
while ($i) {
|
||||||
|
$a = $b->fi($a); #1
|
||||||
|
$a = $b->fi($a); #2
|
||||||
|
$a = $b->fi($a); #3
|
||||||
|
$a = $b->fi($a); #4
|
||||||
|
$a = $b->fi($a); #5
|
||||||
|
$a = $b->fi($a); #6
|
||||||
|
$a = $b->fi($a); #7
|
||||||
|
$a = $b->fi($a); #8
|
||||||
|
$a = $b->fi($a); #9
|
||||||
|
$a = $b->fi($a); #10
|
||||||
|
$a = $b->fi($a); #1
|
||||||
|
$a = $b->fi($a); #2
|
||||||
|
$a = $b->fi($a); #3
|
||||||
|
$a = $b->fi($a); #4
|
||||||
|
$a = $b->fi($a); #5
|
||||||
|
$a = $b->fi($a); #6
|
||||||
|
$a = $b->fi($a); #7
|
||||||
|
$a = $b->fi($a); #8
|
||||||
|
$a = $b->fi($a); #9
|
||||||
|
$a = $b->fi($a); #20
|
||||||
|
$i -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print $a . "\n";
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
54
Examples/test-suite/php/director_protected_runme.php
Normal file
54
Examples/test-suite/php/director_protected_runme.php
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_protected.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_pong,foo_s,foo_q,foo_ping,foo_pang,foo_used,bar_create,bar_pong,bar_used,bar_ping,bar_pang,a_draw,b_draw));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Foo,Bar,PrivateFoo,A,B,AA,BB));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array(bar_a));
|
||||||
|
|
||||||
|
class FooBar extends Bar {
|
||||||
|
protected function ping() {
|
||||||
|
return "FooBar::ping();";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FooBar2 extends Bar {
|
||||||
|
function ping() {
|
||||||
|
return "FooBar2::ping();";
|
||||||
|
}
|
||||||
|
|
||||||
|
function pang() {
|
||||||
|
return "FooBar2::pang();";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new Bar();
|
||||||
|
$f = $b->create();
|
||||||
|
$fb = new FooBar();
|
||||||
|
$fb2 = new FooBar2();
|
||||||
|
|
||||||
|
check::equal($fb->used(), "Foo::pang();Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::used");
|
||||||
|
|
||||||
|
check::equal($fb2->used(), "FooBar2::pang();Bar::pong();Foo::pong();FooBar2::ping();", "bad FooBar2::used");
|
||||||
|
|
||||||
|
check::equal($b->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Bar::pong");
|
||||||
|
|
||||||
|
check::equal($f->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Foo::pong");
|
||||||
|
|
||||||
|
check::equal($fb->pong(), "Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::pong");
|
||||||
|
|
||||||
|
$method = new ReflectionMethod('Bar', 'ping');
|
||||||
|
check::equal($method->isProtected(), true, "Boo::ping should be protected");
|
||||||
|
|
||||||
|
$method = new ReflectionMethod('Foo', 'ping');
|
||||||
|
check::equal($method->isProtected(), true, "Foo::ping should be protected");
|
||||||
|
|
||||||
|
$method = new ReflectionMethod('FooBar', 'pang');
|
||||||
|
check::equal($method->isProtected(), true, "FooBar::pang should be protected");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
60
Examples/test-suite/php/director_stl_runme.php
Normal file
60
Examples/test-suite/php/director_stl_runme.php
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_stl.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_bar,foo_ping,foo_pong,foo_tping,foo_tpong,foo_pident,foo_vident,foo_vsecond,foo_tpident,foo_tvident,foo_tvsecond,foo_vidents,foo_tvidents));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Foo));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
class MyFoo extends Foo {
|
||||||
|
function ping($s) {
|
||||||
|
return "MyFoo::ping():" . $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pident($arg) {
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
function vident($v) {
|
||||||
|
return $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
function vidents($v) {
|
||||||
|
return $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
function vsecond($v1, $v2) {
|
||||||
|
return $v2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new MyFoo();
|
||||||
|
|
||||||
|
$a->tping("hello");
|
||||||
|
$a->tpong("hello");
|
||||||
|
|
||||||
|
# TODO: automatic conversion between PHP arrays and std::pair or
|
||||||
|
# std::vector is not yet implemented.
|
||||||
|
/*$p = array(1, 2);
|
||||||
|
$a->pident($p);
|
||||||
|
$v = array(3, 4);
|
||||||
|
$a->vident($v);
|
||||||
|
|
||||||
|
$a->tpident($p);
|
||||||
|
$a->tvident($v);
|
||||||
|
|
||||||
|
$v1 = array(3, 4);
|
||||||
|
$v2 = array(5, 6);
|
||||||
|
|
||||||
|
$a->tvsecond($v1, $v2);
|
||||||
|
|
||||||
|
$vs = array("hi", "hello");
|
||||||
|
$vs;
|
||||||
|
$a->tvidents($vs);*/
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
34
Examples/test-suite/php/director_string_runme.php
Normal file
34
Examples/test-suite/php/director_string_runme.php
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_string.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(a_get_first,a_call_get_first,a_string_length,a_process_text,a_call_process_func,stringvector_size,stringvector_is_empty,stringvector_clear,stringvector_push,stringvector_pop));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(A,StringVector));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array(a,a_call,a_m_strings,stringvector));
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
function get_first() {
|
||||||
|
return parent::get_first() . " world!";
|
||||||
|
}
|
||||||
|
|
||||||
|
function process_text($string) {
|
||||||
|
parent::process_text($string);
|
||||||
|
$this->smem = "hello";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new B("hello");
|
||||||
|
|
||||||
|
$b->get(0);
|
||||||
|
check::equal($b->get_first(),"hello world!", "get_first failed");
|
||||||
|
|
||||||
|
$b->call_process_func();
|
||||||
|
|
||||||
|
check::equal($b->smem, "hello", "smem failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
29
Examples/test-suite/php/director_thread_runme.php
Normal file
29
Examples/test-suite/php/director_thread_runme.php
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_thread.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(millisecondsleep,foo_stop,foo_run,foo_do_foo));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(director_thread,Foo));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array(foo_val));
|
||||||
|
|
||||||
|
class Derived extends Foo {
|
||||||
|
function do_foo() {
|
||||||
|
$this->val = $this->val - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$d = new Derived();
|
||||||
|
$d->run();
|
||||||
|
|
||||||
|
if ($d->val >= 0) {
|
||||||
|
check::fail($d->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
$d->stop();
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
29
Examples/test-suite/php/director_unroll_runme.php
Normal file
29
Examples/test-suite/php/director_unroll_runme.php
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_unroll.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_ping,foo_pong));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Foo,Bar));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array(bar));
|
||||||
|
|
||||||
|
class MyFoo extends Foo {
|
||||||
|
function ping() {
|
||||||
|
return "MyFoo::ping()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new MyFoo();
|
||||||
|
|
||||||
|
$b = new Bar();
|
||||||
|
|
||||||
|
$b->set($a);
|
||||||
|
$c = $b->get();
|
||||||
|
|
||||||
|
check::equal($a->this, $c->this, "this failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
|
|
@ -31,7 +31,8 @@ $spam=new spam();
|
||||||
check::is_a($spam,"spam");
|
check::is_a($spam,"spam");
|
||||||
check::equal(1,$spam->_foo,"1==spam->_foo");
|
check::equal(1,$spam->_foo,"1==spam->_foo");
|
||||||
check::equal(2,$spam->_bar,"2==spam->_bar");
|
check::equal(2,$spam->_bar,"2==spam->_bar");
|
||||||
check::equal(3,$spam->_baz,"3==spam->_baz");
|
// multiple inheritance not supported in PHP
|
||||||
|
check::equal(null,$spam->_baz,"null==spam->_baz");
|
||||||
check::equal(4,$spam->_spam,"4==spam->_spam");
|
check::equal(4,$spam->_spam,"4==spam->_spam");
|
||||||
|
|
||||||
check::done();
|
check::done();
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,11 @@ check::classes(array(doubleArray));
|
||||||
// now new vars
|
// now new vars
|
||||||
check::globals(array());
|
check::globals(array());
|
||||||
|
|
||||||
|
$d = new doubleArray(10);
|
||||||
|
|
||||||
|
$d->setitem(0, 7);
|
||||||
|
$d->setitem(5, $d->getitem(0) + 3);
|
||||||
|
check::equal($d->getitem(0) + $d->getitem(5), 17., "7+10==17");
|
||||||
|
|
||||||
check::done();
|
check::done();
|
||||||
?>
|
?>
|
||||||
|
|
|
||||||
22
Examples/test-suite/php/li_factory_runme.php
Normal file
22
Examples/test-suite/php/li_factory_runme.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "li_factory.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(geometry_draw,geometry_create,geometry_clone_,point_draw,point_width,point_clone_,circle_draw,circle_radius,circle_clone_));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Geometry,Point,Circle));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
$circle = Geometry::create(Geometry::CIRCLE);
|
||||||
|
$r = $circle->radius();
|
||||||
|
check::equal($r, 1.5, "r failed");
|
||||||
|
|
||||||
|
$point = Geometry::create(Geometry::POINT);
|
||||||
|
$w = $point->width();
|
||||||
|
check::equal($w, 1.0, "w failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
20
Examples/test-suite/php/newobject1_runme.php
Normal file
20
Examples/test-suite/php/newobject1_runme.php
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
// Sample test file
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "newobject1.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_makefoo,foo_makemore,foo_foocount));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(Foo));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
$foo = Foo::makeFoo();
|
||||||
|
check::equal(get_class($foo), "Foo", "static failed");
|
||||||
|
$bar = $foo->makeMore();
|
||||||
|
check::equal(get_class($bar), "Foo", "regular failed");
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
19
Examples/test-suite/php/prefix_runme.php
Normal file
19
Examples/test-suite/php/prefix_runme.php
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
// Sample test file
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "prefix.php";
|
||||||
|
|
||||||
|
// No new functions
|
||||||
|
check::functions(array(foo_get_self));
|
||||||
|
// No new classes
|
||||||
|
check::classes(array(ProjectFoo));
|
||||||
|
// now new vars
|
||||||
|
check::globals(array());
|
||||||
|
|
||||||
|
$f = new ProjectFoo();
|
||||||
|
// This resulted in "Fatal error: Class 'Foo' not found"
|
||||||
|
$f->get_self();
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
|
|
@ -34,8 +34,11 @@ class check {
|
||||||
$df=array_flip($df[internal]);
|
$df=array_flip($df[internal]);
|
||||||
foreach($_original_functions[internal] as $func) unset($df[$func]);
|
foreach($_original_functions[internal] as $func) unset($df[$func]);
|
||||||
// Now chop out any get/set accessors
|
// Now chop out any get/set accessors
|
||||||
foreach(array_keys($df) as $func) if (GETSET && ereg('_[gs]et$',$func)) $extrags[]=$func;
|
foreach(array_keys($df) as $func)
|
||||||
else $extra[]=$func;
|
if ((GETSET && ereg('_[gs]et$',$func)) || ereg('^new_', $func)
|
||||||
|
|| ereg('_(alter|get)_newobject$', $func))
|
||||||
|
$extrags[]=$func;
|
||||||
|
else $extra[]=$func;
|
||||||
// $extra=array_keys($df);
|
// $extra=array_keys($df);
|
||||||
}
|
}
|
||||||
if ($gs) return $extrags;
|
if ($gs) return $extrags;
|
||||||
|
|
|
||||||
14
Examples/test-suite/prefix.i
Normal file
14
Examples/test-suite/prefix.i
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Test that was failing for PHP - the value of the -prefix option was
|
||||||
|
// ignored
|
||||||
|
%module prefix
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
Foo *get_self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
%}
|
||||||
14
Examples/test-suite/python/special_variable_macros_runme.py
Normal file
14
Examples/test-suite/python/special_variable_macros_runme.py
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import special_variable_macros
|
||||||
|
|
||||||
|
name = special_variable_macros.Name()
|
||||||
|
if special_variable_macros.testFred(name) != "none":
|
||||||
|
raise "test failed"
|
||||||
|
if special_variable_macros.testJack(name) != "$specialname":
|
||||||
|
raise "test failed"
|
||||||
|
if special_variable_macros.testJill(name) != "jilly":
|
||||||
|
raise "test failed"
|
||||||
|
if special_variable_macros.testMary(name) != "SWIGTYPE_p_NameWrap":
|
||||||
|
raise "test failed"
|
||||||
|
if special_variable_macros.testJim(name) != "multiname num":
|
||||||
|
raise "test failed"
|
||||||
|
|
||||||
145
Examples/test-suite/special_variable_macros.i
Normal file
145
Examples/test-suite/special_variable_macros.i
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
%module special_variable_macros
|
||||||
|
|
||||||
|
// test $typemap() special variable function
|
||||||
|
// these tests are not typical of how $typemap() should be used, but it checks that it is mostly working
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
struct Name {
|
||||||
|
Name(const char *n="none") : name(n) {}
|
||||||
|
const char *getName() const { return name; };
|
||||||
|
Name *getNamePtr() { return this; };
|
||||||
|
private:
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
struct NameWrap {
|
||||||
|
NameWrap(const char *n="casternone") : name(n) {}
|
||||||
|
Name *getNamePtr() { return &name; };
|
||||||
|
private:
|
||||||
|
Name name;
|
||||||
|
};
|
||||||
|
%}
|
||||||
|
|
||||||
|
// check $1 and $input get expanded properly when used from $typemap()
|
||||||
|
%typemap(in) Name *GENERIC ($*1_type temp)
|
||||||
|
%{
|
||||||
|
/*%typemap(in) Name *GENERIC start */
|
||||||
|
temp = Name("$specialname");
|
||||||
|
(void)$input;
|
||||||
|
$1 = ($1_ltype) &temp;
|
||||||
|
/*%typemap(in) Name *GENERIC end */
|
||||||
|
%}
|
||||||
|
|
||||||
|
// This would never be done in real code, it is just a test of what madness can be done.
|
||||||
|
// Note that the special variable substitutions $*1_type, $descriptor etc are for NameWrap
|
||||||
|
// even when used within the Name typemap via $typemap. I can't think of any useful use cases
|
||||||
|
// for this behaviour in the C/C++ typemaps, but it is possible.
|
||||||
|
%typemap(in) NameWrap *NAMEWRAP ($*1_type temp)
|
||||||
|
%{
|
||||||
|
/*%typemap(in) NameWrap *NAMEWRAP start */
|
||||||
|
temp = $*1_ltype("$descriptor");
|
||||||
|
(void)$input;
|
||||||
|
$1 = temp.getNamePtr();
|
||||||
|
/*%typemap(in) NameWrap *NAMEWRAP end */
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// This should use Name *GENERIC typemap which ignores passed in Name * and instead uses a newly a newly constructed Name
|
||||||
|
// held in a typemap variable with name="$specialname"
|
||||||
|
%typemap(in) Name *jack {
|
||||||
|
// %typemap(in) Name *jack start
|
||||||
|
$typemap(in, Name *GENERIC)
|
||||||
|
// %typemap(in) Name *jack end
|
||||||
|
}
|
||||||
|
|
||||||
|
// as above, but also perform variable substitution
|
||||||
|
%typemap(in) Name *jill {
|
||||||
|
// %typemap(in) Name *jill start
|
||||||
|
$typemap(in, Name *GENERIC, specialname=jilly)
|
||||||
|
// %typemap(in) Name *jill end
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(in) Name *mary {
|
||||||
|
// %typemap(in) Name *mary start
|
||||||
|
$typemap(in, NameWrap *NAMEWRAP)
|
||||||
|
// %typemap(in) Name *mary end
|
||||||
|
}
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
const char * testFred(Name *fred) {
|
||||||
|
return fred->getName();
|
||||||
|
}
|
||||||
|
const char * testJack(Name *jack) {
|
||||||
|
return jack->getName();
|
||||||
|
}
|
||||||
|
const char * testJill(Name *jill) {
|
||||||
|
return jill->getName();
|
||||||
|
}
|
||||||
|
const char * testMary(Name *mary) {
|
||||||
|
return mary->getName();
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Multi-arg typemap lookup
|
||||||
|
// One would never do something like this in reality, it just checks $typemap with multi-arg typemaps
|
||||||
|
%typemap(in) (Name *multiname, int num)($*1_type temp_name, $2_ltype temp_count)
|
||||||
|
%{
|
||||||
|
/*%typemap(in) (Name *multiname, int num) start */
|
||||||
|
temp_name = $*1_ltype("multiname num");
|
||||||
|
temp_count = strlen(temp_name.getNamePtr()->getName());
|
||||||
|
(void)$input;
|
||||||
|
$1 = temp_name.getNamePtr();
|
||||||
|
$2 = temp_count + 100;
|
||||||
|
/*%typemap(in) (Name *multiname, int num) end */
|
||||||
|
%}
|
||||||
|
|
||||||
|
%typemap(in) (Name *jim, int count) {
|
||||||
|
// %typemap(in) Name *jim start
|
||||||
|
$typemap(in, (Name *multiname, int num))
|
||||||
|
// %typemap(in) Name *jim end
|
||||||
|
}
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
const char * testJim(Name *jim, int count) {
|
||||||
|
if (count != strlen(jim->getNamePtr()->getName()) + 100)
|
||||||
|
return "size check failed";
|
||||||
|
else
|
||||||
|
return jim->getName();
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// A real use case for $typemap
|
||||||
|
|
||||||
|
#if defined(SWIGCSHARP)
|
||||||
|
%typemap(cscode) Space::RenameMe %{
|
||||||
|
public static NewName factory(String s) {
|
||||||
|
//below should expand to:
|
||||||
|
//return new NewName( new Name(s) );
|
||||||
|
return new $typemap(cstype, Space::RenameMe)( new $typemap(cstype, Name)(s) );
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
#elif defined(SWIGJAVA)
|
||||||
|
%typemap(javacode) Space::RenameMe %{
|
||||||
|
public static NewName factory(String s) {
|
||||||
|
//below should expand to:
|
||||||
|
//return new NewName( new Name(s) );
|
||||||
|
return new $typemap(jstype, Space::RenameMe)( new $typemap(jstype, Name)(s) );
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%rename(NewName) Space::RenameMe;
|
||||||
|
%inline %{
|
||||||
|
namespace Space {
|
||||||
|
struct RenameMe {
|
||||||
|
RenameMe(Name n) : storedName(n) {}
|
||||||
|
Name getStoredName() { return storedName; }
|
||||||
|
private:
|
||||||
|
Name storedName;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
%module template_default
|
%module template_default
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) ns1::Traits::c; /* Ruby, wrong constant name */
|
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) ns1::Traits::c; /* Ruby, wrong constant name */
|
||||||
|
|
||||||
namespace ns1 {
|
namespace ns1 {
|
||||||
namespace ns2 {
|
namespace ns2 {
|
||||||
|
|
||||||
|
|
@ -154,8 +153,8 @@ namespace ns1 {
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
%template(Do) ns1::ns4::D<ns1::Traits>;
|
%template(Doo) ns1::ns4::D<ns1::Traits>;
|
||||||
%template(Bo) ns1::ns4::Base<ns1::Traits, ns1::ns4::D<ns1::Traits> >;
|
%template(Boo) ns1::ns4::Base<ns1::Traits, ns1::ns4::D<ns1::Traits> >;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
enum Polarization { UnaryPolarization, BinaryPolarization };
|
enum Polarization { UnaryPolarization, BinaryPolarization };
|
||||||
|
|
||||||
template <Polarization P>
|
template <Polarization P>
|
||||||
struct Interface
|
struct Interface_tpl
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
template <class C,
|
template <class C,
|
||||||
Polarization P = C::pmode,
|
Polarization P = C::pmode,
|
||||||
class Base = Interface<P> > // **** problem here *****
|
class Base = Interface_tpl<P> > // **** problem here *****
|
||||||
struct Module : Base
|
struct Module : Base
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
@ -29,12 +29,12 @@
|
||||||
|
|
||||||
namespace oss
|
namespace oss
|
||||||
{
|
{
|
||||||
%template(Interface_UP) Interface<UnaryPolarization>;
|
%template(Interface_UP) Interface_tpl<UnaryPolarization>;
|
||||||
|
|
||||||
// This works
|
// This works
|
||||||
%template(Module_UP1) Module<traits,
|
%template(Module_UP1) Module<traits,
|
||||||
UnaryPolarization,
|
UnaryPolarization,
|
||||||
Interface<UnaryPolarization> >;
|
Interface_tpl<UnaryPolarization> >;
|
||||||
|
|
||||||
// These don't
|
// These don't
|
||||||
%template(Module_UP2) Module<traits, UnaryPolarization>;
|
%template(Module_UP2) Module<traits, UnaryPolarization>;
|
||||||
|
|
|
||||||
198
Lib/php/director.swg
Normal file
198
Lib/php/director.swg
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* See the LICENSE file for information on copyright, usage and redistribution
|
||||||
|
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
|
||||||
|
*
|
||||||
|
* director.swg
|
||||||
|
*
|
||||||
|
* This file contains support for director classes that proxy
|
||||||
|
* method calls from C++ to PHP extensions.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef SWIG_DIRECTOR_PHP_HEADER_
|
||||||
|
#define SWIG_DIRECTOR_PHP_HEADER_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the
|
||||||
|
'Swig' namespace. This could be useful for multi-modules projects.
|
||||||
|
*/
|
||||||
|
#ifdef SWIG_DIRECTOR_STATIC
|
||||||
|
/* Force anonymous (static) namespace */
|
||||||
|
#define Swig
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Swig {
|
||||||
|
/* memory handler */
|
||||||
|
struct GCItem
|
||||||
|
{
|
||||||
|
virtual ~GCItem() {}
|
||||||
|
|
||||||
|
virtual int get_own() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCItem_var
|
||||||
|
{
|
||||||
|
GCItem_var(GCItem *item = 0) : _item(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GCItem_var& operator=(GCItem *item)
|
||||||
|
{
|
||||||
|
GCItem *tmp = _item;
|
||||||
|
_item = item;
|
||||||
|
delete tmp;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~GCItem_var()
|
||||||
|
{
|
||||||
|
delete _item;
|
||||||
|
}
|
||||||
|
|
||||||
|
GCItem * operator->() const
|
||||||
|
{
|
||||||
|
return _item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GCItem *_item;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCItem_Object : GCItem
|
||||||
|
{
|
||||||
|
GCItem_Object(int own) : _own(own)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~GCItem_Object()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_own() const
|
||||||
|
{
|
||||||
|
return _own;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _own;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
struct GCItem_T : GCItem
|
||||||
|
{
|
||||||
|
GCItem_T(Type *ptr) : _ptr(ptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~GCItem_T()
|
||||||
|
{
|
||||||
|
delete _ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Director {
|
||||||
|
protected:
|
||||||
|
zval *swig_self;
|
||||||
|
typedef std::map<void*, GCItem_var> ownership_map;
|
||||||
|
mutable ownership_map owner;
|
||||||
|
public:
|
||||||
|
Director(zval* self) : swig_self(self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~Director() {
|
||||||
|
for (ownership_map::iterator i = owner.begin(); i != owner.end(); i++) {
|
||||||
|
owner.erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_overriden_method(char *cname, char *lc_fname) {
|
||||||
|
zval classname;
|
||||||
|
zend_class_entry **ce;
|
||||||
|
zend_function *mptr;
|
||||||
|
int name_len = strlen(lc_fname);
|
||||||
|
|
||||||
|
ZVAL_STRING(&classname, cname, 0);
|
||||||
|
if (zend_lookup_class(Z_STRVAL_P(&classname), Z_STRLEN_P(&classname), &ce TSRMLS_CC) != SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (zend_hash_find(&(*ce)->function_table, lc_fname, name_len + 1, (void**) &mptr) != SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// common.scope points to the declaring class
|
||||||
|
return strcmp(mptr->common.scope->name, cname);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
void swig_acquire_ownership(Type *vptr) const
|
||||||
|
{
|
||||||
|
if (vptr) {
|
||||||
|
owner[vptr] = new GCItem_T<Type>(vptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* base class for director exceptions */
|
||||||
|
class DirectorException {
|
||||||
|
protected:
|
||||||
|
std::string swig_msg;
|
||||||
|
public:
|
||||||
|
DirectorException(int code, const char *hdr, const char* msg)
|
||||||
|
: swig_msg(hdr)
|
||||||
|
{
|
||||||
|
if (strlen(msg)) {
|
||||||
|
swig_msg += " ";
|
||||||
|
swig_msg += msg;
|
||||||
|
}
|
||||||
|
SWIG_ErrorCode() = code;
|
||||||
|
SWIG_ErrorMsg() = swig_msg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raise(int code, const char *hdr, const char* msg)
|
||||||
|
{
|
||||||
|
throw DirectorException(code, hdr, msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* attempt to call a pure virtual method via a director method */
|
||||||
|
class DirectorPureVirtualException : public Swig::DirectorException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DirectorPureVirtualException(const char* msg)
|
||||||
|
: DirectorException(E_ERROR, "Swig director pure virtual method called", msg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raise(const char *msg)
|
||||||
|
{
|
||||||
|
throw DirectorPureVirtualException(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* any php exception that occurs during a director method call */
|
||||||
|
class DirectorMethodException : public Swig::DirectorException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DirectorMethodException(const char* msg = "")
|
||||||
|
: DirectorException(E_ERROR, "Swig director method error", msg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raise(const char *msg)
|
||||||
|
{
|
||||||
|
throw DirectorMethodException(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif
|
||||||
109
Lib/php/factory.i
Normal file
109
Lib/php/factory.i
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
Implement a more natural wrap for factory methods, for example, if
|
||||||
|
you have:
|
||||||
|
|
||||||
|
---- geometry.h --------
|
||||||
|
struct Geometry {
|
||||||
|
enum GeomType{
|
||||||
|
POINT,
|
||||||
|
CIRCLE
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~Geometry() {}
|
||||||
|
virtual int draw() = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Factory method for all the Geometry objects
|
||||||
|
//
|
||||||
|
static Geometry *create(GeomType i);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Point : Geometry {
|
||||||
|
int draw() { return 1; }
|
||||||
|
double width() { return 1.0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Circle : Geometry {
|
||||||
|
int draw() { return 2; }
|
||||||
|
double radius() { return 1.5; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Factory method for all the Geometry objects
|
||||||
|
//
|
||||||
|
Geometry *Geometry::create(GeomType type) {
|
||||||
|
switch (type) {
|
||||||
|
case POINT: return new Point();
|
||||||
|
case CIRCLE: return new Circle();
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---- geometry.h --------
|
||||||
|
|
||||||
|
|
||||||
|
You can use the %factory with the Geometry::create method as follows:
|
||||||
|
|
||||||
|
%newobject Geometry::create;
|
||||||
|
%factory(Geometry *Geometry::create, Point, Circle);
|
||||||
|
%include "geometry.h"
|
||||||
|
|
||||||
|
and Geometry::create will return a 'Point' or 'Circle' instance
|
||||||
|
instead of the plain 'Geometry' type. For example, in python:
|
||||||
|
|
||||||
|
circle = Geometry.create(Geometry.CIRCLE)
|
||||||
|
r = circle.radius()
|
||||||
|
|
||||||
|
where circle is a Circle proxy instance.
|
||||||
|
|
||||||
|
NOTES: remember to fully qualify all the type names and don't
|
||||||
|
use %factory inside a namespace declaration, ie, instead of
|
||||||
|
|
||||||
|
namespace Foo {
|
||||||
|
%factory(Geometry *Geometry::create, Point, Circle);
|
||||||
|
}
|
||||||
|
|
||||||
|
use
|
||||||
|
|
||||||
|
%factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle);
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* for loop for macro with one argument */
|
||||||
|
%define %_formacro_1(macro, arg1,...)macro(arg1)
|
||||||
|
#if #__VA_ARGS__ != "__fordone__"
|
||||||
|
%_formacro_1(macro, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
/* for loop for macro with one argument */
|
||||||
|
%define %formacro_1(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
|
||||||
|
%define %formacro(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
|
||||||
|
|
||||||
|
/* for loop for macro with two arguments */
|
||||||
|
%define %_formacro_2(macro, arg1, arg2, ...)macro(arg1, arg2)
|
||||||
|
#if #__VA_ARGS__ != "__fordone__"
|
||||||
|
%_formacro_2(macro, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
/* for loop for macro with two arguments */
|
||||||
|
%define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef
|
||||||
|
|
||||||
|
%define %_factory_dispatch(Type)
|
||||||
|
if (!dcast) {
|
||||||
|
Type *dobj = dynamic_cast<Type *>($1);
|
||||||
|
if (dobj) {
|
||||||
|
dcast = 1;
|
||||||
|
SWIG_SetPointerZval(return_value, SWIG_as_voidptr(dobj),$descriptor(Type *), $owner);
|
||||||
|
}
|
||||||
|
}%enddef
|
||||||
|
|
||||||
|
%define %factory(Method,Types...)
|
||||||
|
%typemap(out) Method {
|
||||||
|
int dcast = 0;
|
||||||
|
%formacro(%_factory_dispatch, Types)
|
||||||
|
if (!dcast) {
|
||||||
|
SWIG_SetPointerZval(return_value, SWIG_as_voidptr($1),$descriptor, $owner);
|
||||||
|
}
|
||||||
|
}%enddef
|
||||||
|
|
@ -89,6 +89,14 @@
|
||||||
$1 = *tmp;
|
$1 = *tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(directorout) SWIGTYPE ($&1_ltype tmp)
|
||||||
|
{
|
||||||
|
if(SWIG_ConvertPtr(*$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) {
|
||||||
|
SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor");
|
||||||
|
}
|
||||||
|
$result = *tmp;
|
||||||
|
}
|
||||||
|
|
||||||
%typemap(in) SWIGTYPE *,
|
%typemap(in) SWIGTYPE *,
|
||||||
SWIGTYPE []
|
SWIGTYPE []
|
||||||
{
|
{
|
||||||
|
|
@ -176,17 +184,42 @@
|
||||||
ZVAL_LONG(return_value,$1);
|
ZVAL_LONG(return_value,$1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(directorin) int,
|
||||||
|
unsigned int,
|
||||||
|
short,
|
||||||
|
unsigned short,
|
||||||
|
long,
|
||||||
|
unsigned long,
|
||||||
|
signed char,
|
||||||
|
unsigned char,
|
||||||
|
size_t,
|
||||||
|
enum SWIGTYPE
|
||||||
|
{
|
||||||
|
ZVAL_LONG($input,$1_name);
|
||||||
|
}
|
||||||
|
|
||||||
%typemap(out) bool
|
%typemap(out) bool
|
||||||
{
|
{
|
||||||
ZVAL_BOOL(return_value,($1)?1:0);
|
ZVAL_BOOL(return_value,($1)?1:0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(directorin) bool
|
||||||
|
{
|
||||||
|
ZVAL_BOOL($input,($1_name)?1:0);
|
||||||
|
}
|
||||||
|
|
||||||
%typemap(out) float,
|
%typemap(out) float,
|
||||||
double
|
double
|
||||||
{
|
{
|
||||||
ZVAL_DOUBLE(return_value,$1);
|
ZVAL_DOUBLE(return_value,$1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(directorin) float,
|
||||||
|
double
|
||||||
|
{
|
||||||
|
ZVAL_DOUBLE($input,$1_name);
|
||||||
|
}
|
||||||
|
|
||||||
%typemap(out) char
|
%typemap(out) char
|
||||||
{
|
{
|
||||||
ZVAL_STRINGL(return_value,&$1, 1, 1);
|
ZVAL_STRINGL(return_value,&$1, 1, 1);
|
||||||
|
|
@ -209,6 +242,13 @@
|
||||||
SWIG_SetPointerZval(return_value, (void *)$1, $1_descriptor, $owner);
|
SWIG_SetPointerZval(return_value, (void *)$1, $1_descriptor, $owner);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%typemap(directorin) SWIGTYPE *,
|
||||||
|
SWIGTYPE [],
|
||||||
|
SWIGTYPE &
|
||||||
|
%{
|
||||||
|
SWIG_SetPointerZval($input, (void *)&$1_name, $1_descriptor, $owner);
|
||||||
|
%}
|
||||||
|
|
||||||
%typemap(out) SWIGTYPE *DYNAMIC,
|
%typemap(out) SWIGTYPE *DYNAMIC,
|
||||||
SWIGTYPE &DYNAMIC
|
SWIGTYPE &DYNAMIC
|
||||||
{
|
{
|
||||||
|
|
@ -230,6 +270,19 @@
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
%typemap(directorin) SWIGTYPE
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
SWIG_SetPointerZval($input, SWIG_as_voidptr(&$1_name), $&1_descriptor, 2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
$&1_ltype resultobj = ($&1_ltype) emalloc(sizeof($1_type));
|
||||||
|
memcpy(resultobj, &$1, sizeof($1_type));
|
||||||
|
SWIG_SetPointerZval($input, (void *)resultobj, $&1_descriptor, 2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
%typemap(out) void "";
|
%typemap(out) void "";
|
||||||
|
|
||||||
%typemap(out) char [ANY]
|
%typemap(out) char [ANY]
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,13 @@
|
||||||
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
|
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
|
||||||
*
|
*
|
||||||
* phpkw.swg
|
* phpkw.swg
|
||||||
*
|
|
||||||
* The 'keywords' in PHP are global, ie, the following names are fine
|
|
||||||
* when used as class methods.
|
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renamed as 'c_" `x` "'",sourcefmt="%(lower)s", rename="c_%s",fullname=1) `x`
|
#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renamed as 'c_" `x` "'",sourcefmt="%(lower)s",$isclass,rename="c_%s") `x`
|
||||||
|
|
||||||
%define PHPCN(x)
|
#define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name, class renamed as 'c_" `x` "'",%$isclass,rename="c_%s") `x`
|
||||||
%keywordwarn("'" `x` "' is a PHP reserved class name, class renamed as 'c_" `x` "'",%$isclass,rename="c_%s") `x`;
|
|
||||||
%keywordwarn("'" `x` "' is a PHP reserved class name, constructor renamed as 'c_" `x` "'",%$isconstructor,rename="c_%s") `x`;
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
#define PHPBN1(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP",sourcefmt="%(lower)s",fullname=1) `x`
|
#define PHPBN1(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP",sourcefmt="%(lower)s") `x`
|
||||||
#define PHPBN2(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP") "::" `x`
|
#define PHPBN2(x) %builtinwarn("'" `x` "' conflicts with a built-in name in PHP") "::" `x`
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ extern "C" {
|
||||||
#include "zend.h"
|
#include "zend.h"
|
||||||
#include "zend_API.h"
|
#include "zend_API.h"
|
||||||
#include "php.h"
|
#include "php.h"
|
||||||
|
#include "ext/standard/php_string.h"
|
||||||
|
|
||||||
#ifdef ZEND_RAW_FENTRY
|
#ifdef ZEND_RAW_FENTRY
|
||||||
/* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */
|
/* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */
|
||||||
|
|
@ -84,6 +85,7 @@ typedef struct {
|
||||||
static ZEND_RSRC_DTOR_FUNC(SWIG_landfill) { (void)rsrc; }
|
static ZEND_RSRC_DTOR_FUNC(SWIG_landfill) { (void)rsrc; }
|
||||||
|
|
||||||
#define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC)
|
#define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC)
|
||||||
|
#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a))
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) {
|
SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) {
|
||||||
|
|
@ -101,7 +103,31 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject
|
||||||
value=(swig_object_wrapper *)emalloc(sizeof(swig_object_wrapper));
|
value=(swig_object_wrapper *)emalloc(sizeof(swig_object_wrapper));
|
||||||
value->ptr=ptr;
|
value->ptr=ptr;
|
||||||
value->newobject=newobject;
|
value->newobject=newobject;
|
||||||
ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata));
|
if (newobject <= 1) {
|
||||||
|
ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata));
|
||||||
|
} else {
|
||||||
|
value->newobject = 0;
|
||||||
|
zval *resource;
|
||||||
|
MAKE_STD_ZVAL(resource);
|
||||||
|
ZEND_REGISTER_RESOURCE(resource, value, *(int *)(type->clientdata));
|
||||||
|
zend_class_entry **ce = NULL;
|
||||||
|
zval *classname;
|
||||||
|
MAKE_STD_ZVAL(classname);
|
||||||
|
/* _p_Foo -> Foo */
|
||||||
|
ZVAL_STRING(classname, (char*)type->name+3, 1);
|
||||||
|
/* class names are stored in lowercase */
|
||||||
|
php_strtolower(Z_STRVAL_PP(&classname), Z_STRLEN_PP(&classname));
|
||||||
|
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &ce TSRMLS_CC) != SUCCESS) {
|
||||||
|
/* class does not exists */
|
||||||
|
object_init(z);
|
||||||
|
} else {
|
||||||
|
object_init_ex(z, *ce);
|
||||||
|
}
|
||||||
|
z->refcount = 1;
|
||||||
|
z->is_ref = 1;
|
||||||
|
zend_hash_update(HASH_OF(z), (char*)"_cPtr", sizeof("_cPtr"), (void*)&resource, sizeof(zval), NULL);
|
||||||
|
FREE_ZVAL(classname);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zend_error(E_ERROR, "Type: %s not registered with zend",type->name);
|
zend_error(E_ERROR, "Type: %s not registered with zend",type->name);
|
||||||
|
|
@ -156,7 +182,7 @@ SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) {
|
||||||
char *type_name;
|
char *type_name;
|
||||||
|
|
||||||
value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type);
|
value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type);
|
||||||
if ( flags && SWIG_POINTER_DISOWN ) {
|
if ( flags & SWIG_POINTER_DISOWN ) {
|
||||||
value->newobject = 0;
|
value->newobject = 0;
|
||||||
}
|
}
|
||||||
p = value->ptr;
|
p = value->ptr;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@ namespace std {
|
||||||
$1.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input));
|
$1.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input));
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%typemap(directorout) string %{
|
||||||
|
convert_to_string_ex($input);
|
||||||
|
$result.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input));
|
||||||
|
%}
|
||||||
|
|
||||||
%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) const string& %{
|
%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) const string& %{
|
||||||
$1 = ( Z_TYPE_PP($input) == IS_STRING ) ? 1 : 0;
|
$1 = ( Z_TYPE_PP($input) == IS_STRING ) ? 1 : 0;
|
||||||
%}
|
%}
|
||||||
|
|
@ -43,6 +48,10 @@ namespace std {
|
||||||
ZVAL_STRINGL($result, const_cast<char*>($1.data()), $1.size(), 1);
|
ZVAL_STRINGL($result, const_cast<char*>($1.data()), $1.size(), 1);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%typemap(directorin) string %{
|
||||||
|
ZVAL_STRINGL($input, const_cast<char*>($1_name.data()), $1_name.size(), 1);
|
||||||
|
%}
|
||||||
|
|
||||||
%typemap(out) const string & %{
|
%typemap(out) const string & %{
|
||||||
ZVAL_STRINGL($result, const_cast<char*>($1->data()), $1->size(), 1);
|
ZVAL_STRINGL($result, const_cast<char*>($1->data()), $1->size(), 1);
|
||||||
%}
|
%}
|
||||||
|
|
@ -63,6 +72,14 @@ namespace std {
|
||||||
$1 = &temp;
|
$1 = &temp;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%typemap(directorout) string & (std::string *temp) %{
|
||||||
|
convert_to_string_ex($input);
|
||||||
|
temp = new std::string;
|
||||||
|
temp->assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input));
|
||||||
|
swig_acquire_ownership(temp);
|
||||||
|
$result = temp;
|
||||||
|
%}
|
||||||
|
|
||||||
%typemap(argout) string & %{
|
%typemap(argout) string & %{
|
||||||
ZVAL_STRINGL(*($input), const_cast<char*>($1->data()), $1->size(), 1);
|
ZVAL_STRINGL(*($input), const_cast<char*>($1->data()), $1->size(), 1);
|
||||||
%}
|
%}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,10 @@
|
||||||
%{
|
%{
|
||||||
CONVERT_IN($1,$1_ltype,$input);
|
CONVERT_IN($1,$1_ltype,$input);
|
||||||
%}
|
%}
|
||||||
|
%typemap(directorout) TYPE, const TYPE &
|
||||||
|
%{
|
||||||
|
CONVERT_IN($result,$1_ltype,$input);
|
||||||
|
%}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
%fragment("t_output_helper","header") %{
|
%fragment("t_output_helper","header") %{
|
||||||
|
|
@ -49,6 +53,7 @@ t_output_helper( zval **target, zval *o) {
|
||||||
}
|
}
|
||||||
if ( (*target)->type == IS_NULL ) {
|
if ( (*target)->type == IS_NULL ) {
|
||||||
REPLACE_ZVAL_VALUE(target,o,1);
|
REPLACE_ZVAL_VALUE(target,o,1);
|
||||||
|
FREE_ZVAL(o);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zval *tmp;
|
zval *tmp;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
typedef std::map<K,T> map_type;
|
typedef std::map<K,T> map_type;
|
||||||
static int asptr(PyObject *obj, map_type **val) {
|
static int asptr(PyObject *obj, map_type **val) {
|
||||||
int res = SWIG_ERROR;
|
int res = SWIG_ERROR;
|
||||||
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||||
if (PyDict_Check(obj)) {
|
if (PyDict_Check(obj)) {
|
||||||
SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
|
SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
|
||||||
%#if PY_VERSION_HEX >= 0x03000000
|
%#if PY_VERSION_HEX >= 0x03000000
|
||||||
|
|
@ -32,6 +33,7 @@
|
||||||
res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info<map_type>(),0);
|
res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info<map_type>(),0);
|
||||||
if (SWIG_IsOK(res) && val) *val = p;
|
if (SWIG_IsOK(res) && val) *val = p;
|
||||||
}
|
}
|
||||||
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -47,10 +49,10 @@
|
||||||
if (desc && desc->clientdata) {
|
if (desc && desc->clientdata) {
|
||||||
return SWIG_NewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN);
|
return SWIG_NewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN);
|
||||||
} else {
|
} else {
|
||||||
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||||
size_type size = map.size();
|
size_type size = map.size();
|
||||||
int pysize = (size <= (size_type) INT_MAX) ? (int) size : -1;
|
int pysize = (size <= (size_type) INT_MAX) ? (int) size : -1;
|
||||||
if (pysize < 0) {
|
if (pysize < 0) {
|
||||||
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"map size not valid in python");
|
"map size not valid in python");
|
||||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
|
|
@ -62,6 +64,7 @@
|
||||||
swig::SwigVar_PyObject val = swig::from(i->second);
|
swig::SwigVar_PyObject val = swig::from(i->second);
|
||||||
PyDict_SetItem(obj, key, val);
|
PyDict_SetItem(obj, key, val);
|
||||||
}
|
}
|
||||||
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -165,8 +168,8 @@
|
||||||
PyObject* keys() {
|
PyObject* keys() {
|
||||||
Map::size_type size = self->size();
|
Map::size_type size = self->size();
|
||||||
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
|
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
|
||||||
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||||
if (pysize < 0) {
|
if (pysize < 0) {
|
||||||
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"map size not valid in python");
|
"map size not valid in python");
|
||||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
|
|
@ -177,14 +180,15 @@
|
||||||
for (int j = 0; j < pysize; ++i, ++j) {
|
for (int j = 0; j < pysize; ++i, ++j) {
|
||||||
PyList_SET_ITEM(keyList, j, swig::from(i->first));
|
PyList_SET_ITEM(keyList, j, swig::from(i->first));
|
||||||
}
|
}
|
||||||
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
return keyList;
|
return keyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* values() {
|
PyObject* values() {
|
||||||
Map::size_type size = self->size();
|
Map::size_type size = self->size();
|
||||||
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
|
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
|
||||||
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||||
if (pysize < 0) {
|
if (pysize < 0) {
|
||||||
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"map size not valid in python");
|
"map size not valid in python");
|
||||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
|
|
@ -195,14 +199,15 @@
|
||||||
for (int j = 0; j < pysize; ++i, ++j) {
|
for (int j = 0; j < pysize; ++i, ++j) {
|
||||||
PyList_SET_ITEM(valList, j, swig::from(i->second));
|
PyList_SET_ITEM(valList, j, swig::from(i->second));
|
||||||
}
|
}
|
||||||
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
return valList;
|
return valList;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* items() {
|
PyObject* items() {
|
||||||
Map::size_type size = self->size();
|
Map::size_type size = self->size();
|
||||||
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
|
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
|
||||||
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||||
if (pysize < 0) {
|
if (pysize < 0) {
|
||||||
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"map size not valid in python");
|
"map size not valid in python");
|
||||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
|
|
@ -213,6 +218,7 @@
|
||||||
for (int j = 0; j < pysize; ++i, ++j) {
|
for (int j = 0; j < pysize; ++i, ++j) {
|
||||||
PyList_SET_ITEM(itemList, j, swig::from(*i));
|
PyList_SET_ITEM(itemList, j, swig::from(*i));
|
||||||
}
|
}
|
||||||
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||||
return itemList;
|
return itemList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
4
README
4
README
|
|
@ -59,7 +59,11 @@ Major contributors include:
|
||||||
Martin Froehlich <MartinFroehlich@ACM.org> (Guile)
|
Martin Froehlich <MartinFroehlich@ACM.org> (Guile)
|
||||||
Marcio Luis Teixeira <marciot@holly.colostate.edu> (Guile)
|
Marcio Luis Teixeira <marciot@holly.colostate.edu> (Guile)
|
||||||
Duncan Temple Lang (R)
|
Duncan Temple Lang (R)
|
||||||
|
<<<<<<< .working
|
||||||
Baozeng Ding <sploving1@163.com> (Scilab)
|
Baozeng Ding <sploving1@163.com> (Scilab)
|
||||||
|
=======
|
||||||
|
Miklos Vajna <vmiklos@frugalware.org> (PHP directors)
|
||||||
|
>>>>>>> .merge-right.r11488
|
||||||
|
|
||||||
Past contributors include:
|
Past contributors include:
|
||||||
James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
|
James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
|
||||||
|
|
|
||||||
|
|
@ -1465,7 +1465,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
|
||||||
} decl;
|
} decl;
|
||||||
Parm *tparms;
|
Parm *tparms;
|
||||||
struct {
|
struct {
|
||||||
String *op;
|
String *method;
|
||||||
Hash *kwargs;
|
Hash *kwargs;
|
||||||
} tmap;
|
} tmap;
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -2499,10 +2499,10 @@ varargs_parms : parms { $$ = $1; }
|
||||||
|
|
||||||
typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace {
|
typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace {
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
if ($3.op) {
|
if ($3.method) {
|
||||||
String *code = 0;
|
String *code = 0;
|
||||||
$$ = new_node("typemap");
|
$$ = new_node("typemap");
|
||||||
Setattr($$,"method",$3.op);
|
Setattr($$,"method",$3.method);
|
||||||
if ($3.kwargs) {
|
if ($3.kwargs) {
|
||||||
ParmList *kw = $3.kwargs;
|
ParmList *kw = $3.kwargs;
|
||||||
code = remove_block(kw, $6);
|
code = remove_block(kw, $6);
|
||||||
|
|
@ -2516,17 +2516,17 @@ typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace {
|
||||||
}
|
}
|
||||||
| TYPEMAP LPAREN typemap_type RPAREN tm_list SEMI {
|
| TYPEMAP LPAREN typemap_type RPAREN tm_list SEMI {
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
if ($3.op) {
|
if ($3.method) {
|
||||||
$$ = new_node("typemap");
|
$$ = new_node("typemap");
|
||||||
Setattr($$,"method",$3.op);
|
Setattr($$,"method",$3.method);
|
||||||
appendChild($$,$5);
|
appendChild($$,$5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| TYPEMAP LPAREN typemap_type RPAREN tm_list EQUAL typemap_parm SEMI {
|
| TYPEMAP LPAREN typemap_type RPAREN tm_list EQUAL typemap_parm SEMI {
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
if ($3.op) {
|
if ($3.method) {
|
||||||
$$ = new_node("typemapcopy");
|
$$ = new_node("typemapcopy");
|
||||||
Setattr($$,"method",$3.op);
|
Setattr($$,"method",$3.method);
|
||||||
Setattr($$,"pattern", Getattr($7,"pattern"));
|
Setattr($$,"pattern", Getattr($7,"pattern"));
|
||||||
appendChild($$,$5);
|
appendChild($$,$5);
|
||||||
}
|
}
|
||||||
|
|
@ -2546,15 +2546,15 @@ typemap_type : kwargs {
|
||||||
/* two argument typemap form */
|
/* two argument typemap form */
|
||||||
name = Getattr($1,"name");
|
name = Getattr($1,"name");
|
||||||
if (!name || (Strcmp(name,typemap_lang))) {
|
if (!name || (Strcmp(name,typemap_lang))) {
|
||||||
$$.op = 0;
|
$$.method = 0;
|
||||||
$$.kwargs = 0;
|
$$.kwargs = 0;
|
||||||
} else {
|
} else {
|
||||||
$$.op = Getattr(p,"name");
|
$$.method = Getattr(p,"name");
|
||||||
$$.kwargs = nextSibling(p);
|
$$.kwargs = nextSibling(p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* one-argument typemap-form */
|
/* one-argument typemap-form */
|
||||||
$$.op = Getattr($1,"name");
|
$$.method = Getattr($1,"name");
|
||||||
$$.kwargs = p;
|
$$.kwargs = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,7 @@
|
||||||
|
|
||||||
#define WARN_PHP_MULTIPLE_INHERITANCE 870
|
#define WARN_PHP_MULTIPLE_INHERITANCE 870
|
||||||
#define WARN_PHP_UNKNOWN_PRAGMA 871
|
#define WARN_PHP_UNKNOWN_PRAGMA 871
|
||||||
|
#define WARN_PHP_PUBLIC_BASE 872
|
||||||
|
|
||||||
/* please leave 870-889 free for PHP */
|
/* please leave 870-889 free for PHP */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ BUILD_SOURCE_DIR=$(top_builddir)/Source
|
||||||
|
|
||||||
SWIG_CXX_DEFS = @SWILL@
|
SWIG_CXX_DEFS = @SWILL@
|
||||||
|
|
||||||
AM_CFLAGS = -I$(BUILD_SOURCE_DIR)/Include \
|
AM_CPPFLAGS = -I$(BUILD_SOURCE_DIR)/Include \
|
||||||
-I$(BUILD_SOURCE_DIR)/CParse \
|
-I$(BUILD_SOURCE_DIR)/CParse \
|
||||||
-I$(SOURCE_DIR)/Include \
|
-I$(SOURCE_DIR)/Include \
|
||||||
-I$(SOURCE_DIR)/DOH \
|
-I$(SOURCE_DIR)/DOH \
|
||||||
|
|
@ -17,8 +17,7 @@ AM_CFLAGS = -I$(BUILD_SOURCE_DIR)/Include \
|
||||||
-I$(SOURCE_DIR)/Swig \
|
-I$(SOURCE_DIR)/Swig \
|
||||||
-I$(SOURCE_DIR)/Modules
|
-I$(SOURCE_DIR)/Modules
|
||||||
|
|
||||||
AM_CXXFLAGS = $(AM_CFLAGS) \
|
AM_CXXFLAGS = $(SWIG_CXX_DEFS)
|
||||||
$(SWIG_CXX_DEFS)
|
|
||||||
|
|
||||||
AM_YFLAGS = -d
|
AM_YFLAGS = -d
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1803,13 +1803,13 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
|
||||||
String *t2 = Getattr(p2, "tmap:typecheck:precedence");
|
String *t2 = Getattr(p2, "tmap:typecheck:precedence");
|
||||||
if ((!t1) && (!nodes[i].error)) {
|
if ((!t1) && (!nodes[i].error)) {
|
||||||
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
|
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
|
||||||
"Overloaded %s(%s) not supported (no type checking rule for '%s').\n",
|
"Overloaded method %s not supported (no type checking rule for '%s').\n",
|
||||||
Getattr(nodes[i].n, "name"), ParmList_str_defaultargs(Getattr(nodes[i].n, "parms")), SwigType_str(Getattr(p1, "type"), 0));
|
Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
|
||||||
nodes[i].error = 1;
|
nodes[i].error = 1;
|
||||||
} else if ((!t2) && (!nodes[j].error)) {
|
} else if ((!t2) && (!nodes[j].error)) {
|
||||||
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
|
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
|
||||||
"Overloaded %s(%s) not supported (no type checking rule for '%s').\n",
|
"Overloaded method %s not supported (no type checking rule for '%s').\n",
|
||||||
Getattr(nodes[j].n, "name"), ParmList_str_defaultargs(Getattr(nodes[j].n, "parms")), SwigType_str(Getattr(p2, "type"), 0));
|
Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
|
||||||
nodes[j].error = 1;
|
nodes[j].error = 1;
|
||||||
}
|
}
|
||||||
if (t1 && t2) {
|
if (t1 && t2) {
|
||||||
|
|
@ -1937,19 +1937,15 @@ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
|
||||||
if (!nodes[j].error) {
|
if (!nodes[j].error) {
|
||||||
if (script_lang_wrapping) {
|
if (script_lang_wrapping) {
|
||||||
Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
|
Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
|
||||||
"Overloaded %s(%s)%s is shadowed by %s(%s)%s at %s:%d.\n",
|
"Overloaded method %s is shadowed by %s at %s:%d.\n",
|
||||||
Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms),
|
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
|
||||||
SwigType_isconst(Getattr(nodes[j].n, "decl")) ? " const" : "",
|
Getfile(nodes[i].n), Getline(nodes[i].n));
|
||||||
Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms),
|
|
||||||
SwigType_isconst(Getattr(nodes[i].n, "decl")) ? " const" : "", Getfile(nodes[i].n), Getline(nodes[i].n));
|
|
||||||
} else {
|
} else {
|
||||||
if (!Getattr(nodes[j].n, "overload:ignore"))
|
if (!Getattr(nodes[j].n, "overload:ignore"))
|
||||||
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
|
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
|
||||||
"Overloaded method %s(%s)%s ignored. Method %s(%s)%s at %s:%d used.\n",
|
"Overloaded method %s ignored. Method %s at %s:%d used.\n",
|
||||||
Getattr(nodes[j].n, "name"), ParmList_errorstr(nodes[j].parms),
|
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
|
||||||
SwigType_isconst(Getattr(nodes[j].n, "decl")) ? " const" : "",
|
Getfile(nodes[i].n), Getline(nodes[i].n));
|
||||||
Getattr(nodes[i].n, "name"), ParmList_errorstr(nodes[i].parms),
|
|
||||||
SwigType_isconst(Getattr(nodes[i].n, "decl")) ? " const" : "", Getfile(nodes[i].n), Getline(nodes[i].n));
|
|
||||||
}
|
}
|
||||||
nodes[j].error = 1;
|
nodes[j].error = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -2010,7 +2006,7 @@ Node *parent_node_skipping_extends(Node *n) {
|
||||||
* emit_num_lin_arguments()
|
* emit_num_lin_arguments()
|
||||||
*
|
*
|
||||||
* Calculate the total number of arguments. This function is safe for use
|
* Calculate the total number of arguments. This function is safe for use
|
||||||
* with multi-valued typemaps which may change the number of arguments in
|
* with multi-argument typemaps which may change the number of arguments in
|
||||||
* strange ways.
|
* strange ways.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2766,6 +2766,16 @@ public:
|
||||||
Delete(func_name);
|
Delete(func_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
* replaceSpecialVariables()
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
|
||||||
|
(void)method;
|
||||||
|
SwigType *type = Getattr(parm, "type");
|
||||||
|
substituteClassname(type, tm);
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
* decodeEnumFeature()
|
* decodeEnumFeature()
|
||||||
* Decode the possible enum features, which are one of:
|
* Decode the possible enum features, which are one of:
|
||||||
|
|
@ -2859,15 +2869,15 @@ public:
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* substituteClassname()
|
* substituteClassname()
|
||||||
*
|
*
|
||||||
* Substitute $csclassname with the proxy class name for classes/structs/unions that SWIG knows about.
|
* Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
|
||||||
* Also substitutes enums with enum name.
|
* that SWIG knows about. Also substitutes enums with enum name.
|
||||||
* Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
|
* Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
|
||||||
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
|
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* pt - parameter type
|
* pt - parameter type
|
||||||
* tm - cstype typemap
|
* tm - typemap contents that might contain the special variable to be replaced
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* tm - cstype typemap with $csclassname substitution
|
* tm - typemap contents complete with the special variable substitution
|
||||||
* Return:
|
* Return:
|
||||||
* substitution_performed - flag indicating if a substitution was performed
|
* substitution_performed - flag indicating if a substitution was performed
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
@ -3029,7 +3039,7 @@ public:
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* typemapLookup()
|
* typemapLookup()
|
||||||
* n - for input only and must contain info for Getfile(n) and Getline(n) to work
|
* n - for input only and must contain info for Getfile(n) and Getline(n) to work
|
||||||
* op - typemap method name
|
* tmap_method - typemap method name
|
||||||
* type - typemap type to lookup
|
* type - typemap type to lookup
|
||||||
* warning - warning number to issue if no typemaps found
|
* warning - warning number to issue if no typemaps found
|
||||||
* typemap_attributes - the typemap attributes are attached to this node and will
|
* typemap_attributes - the typemap attributes are attached to this node and will
|
||||||
|
|
@ -3037,16 +3047,16 @@ public:
|
||||||
* return is never NULL, unlike Swig_typemap_lookup()
|
* return is never NULL, unlike Swig_typemap_lookup()
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
const String *typemapLookup(Node *n, const_String_or_char_ptr op, SwigType *type, int warning, Node *typemap_attributes = 0) {
|
const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
|
||||||
Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
|
Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
|
||||||
Setattr(node, "type", type);
|
Setattr(node, "type", type);
|
||||||
Setfile(node, Getfile(n));
|
Setfile(node, Getfile(n));
|
||||||
Setline(node, Getline(n));
|
Setline(node, Getline(n));
|
||||||
const String *tm = Swig_typemap_lookup(op, node, "", 0);
|
const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
|
||||||
if (!tm) {
|
if (!tm) {
|
||||||
tm = empty_string;
|
tm = empty_string;
|
||||||
if (warning != WARN_NONE)
|
if (warning != WARN_NONE)
|
||||||
Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", op, SwigType_str(type, 0));
|
Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
|
||||||
}
|
}
|
||||||
if (!typemap_attributes)
|
if (!typemap_attributes)
|
||||||
Delete(node);
|
Delete(node);
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
|
||||||
* emit_num_arguments()
|
* emit_num_arguments()
|
||||||
*
|
*
|
||||||
* Calculate the total number of arguments. This function is safe for use
|
* Calculate the total number of arguments. This function is safe for use
|
||||||
* with multi-valued typemaps which may change the number of arguments in
|
* with multi-argument typemaps which may change the number of arguments in
|
||||||
* strange ways.
|
* strange ways.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
@ -232,7 +232,7 @@ int emit_num_arguments(ParmList *parms) {
|
||||||
* emit_num_required()
|
* emit_num_required()
|
||||||
*
|
*
|
||||||
* Computes the number of required arguments. This function is safe for
|
* Computes the number of required arguments. This function is safe for
|
||||||
* use with multi-valued typemaps and knows how to skip over everything
|
* use with multi-argument typemaps and knows how to skip over everything
|
||||||
* properly. Note that parameters with default values are counted unless
|
* properly. Note that parameters with default values are counted unless
|
||||||
* the compact default args option is on.
|
* the compact default args option is on.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -2603,6 +2603,16 @@ public:
|
||||||
Delete(func_name);
|
Delete(func_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
* replaceSpecialVariables()
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
|
||||||
|
(void)method;
|
||||||
|
SwigType *type = Getattr(parm, "type");
|
||||||
|
substituteClassname(type, tm);
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
* decodeEnumFeature()
|
* decodeEnumFeature()
|
||||||
* Decode the possible enum features, which are one of:
|
* Decode the possible enum features, which are one of:
|
||||||
|
|
@ -2700,16 +2710,16 @@ public:
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* substituteClassname()
|
* substituteClassname()
|
||||||
*
|
*
|
||||||
* Substitute $javaclassname with the proxy class name for classes/structs/unions that SWIG knows about.
|
* Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions
|
||||||
* Also substitutes enums with enum name.
|
* that SWIG knows about. Also substitutes enums with enum name.
|
||||||
* Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
|
* Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
|
||||||
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
|
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* pt - parameter type
|
* pt - parameter type
|
||||||
* tm - jstype typemap
|
* tm - typemap contents that might contain the special variable to be replaced
|
||||||
* jnidescriptor - if set, inner class names are separated with '$' otherwise a '.'
|
* jnidescriptor - if set, inner class names are separated with '$' otherwise a '.'
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* tm - jstype typemap with $javaclassname substitution
|
* tm - typemap contents complete with the special variable substitution
|
||||||
* Return:
|
* Return:
|
||||||
* substitution_performed - flag indicating if a substitution was performed
|
* substitution_performed - flag indicating if a substitution was performed
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
@ -2862,7 +2872,7 @@ public:
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* typemapLookup()
|
* typemapLookup()
|
||||||
* n - for input only and must contain info for Getfile(n) and Getline(n) to work
|
* n - for input only and must contain info for Getfile(n) and Getline(n) to work
|
||||||
* op - typemap method name
|
* tmap_method - typemap method name
|
||||||
* type - typemap type to lookup
|
* type - typemap type to lookup
|
||||||
* warning - warning number to issue if no typemaps found
|
* warning - warning number to issue if no typemaps found
|
||||||
* typemap_attributes - the typemap attributes are attached to this node and will
|
* typemap_attributes - the typemap attributes are attached to this node and will
|
||||||
|
|
@ -2870,16 +2880,16 @@ public:
|
||||||
* return is never NULL, unlike Swig_typemap_lookup()
|
* return is never NULL, unlike Swig_typemap_lookup()
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
const String *typemapLookup(Node *n, const_String_or_char_ptr op, SwigType *type, int warning, Node *typemap_attributes = 0) {
|
const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
|
||||||
Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
|
Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
|
||||||
Setattr(node, "type", type);
|
Setattr(node, "type", type);
|
||||||
Setfile(node, Getfile(n));
|
Setfile(node, Getfile(n));
|
||||||
Setline(node, Getline(n));
|
Setline(node, Getline(n));
|
||||||
const String *tm = Swig_typemap_lookup(op, node, "", 0);
|
const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
|
||||||
if (!tm) {
|
if (!tm) {
|
||||||
tm = empty_string;
|
tm = empty_string;
|
||||||
if (warning != WARN_NONE)
|
if (warning != WARN_NONE)
|
||||||
Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", op, SwigType_str(type, 0));
|
Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
|
||||||
}
|
}
|
||||||
if (!typemap_attributes)
|
if (!typemap_attributes)
|
||||||
Delete(node);
|
Delete(node);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ static int director_mode = 0;
|
||||||
static int director_protected_mode = 1;
|
static int director_protected_mode = 1;
|
||||||
static int all_protected_mode = 0;
|
static int all_protected_mode = 0;
|
||||||
static int naturalvar_mode = 0;
|
static int naturalvar_mode = 0;
|
||||||
|
Language* Language::this_ = 0;
|
||||||
|
|
||||||
/* Set director_protected_mode */
|
/* Set director_protected_mode */
|
||||||
void Wrapper_director_mode_set(int flag) {
|
void Wrapper_director_mode_set(int flag) {
|
||||||
|
|
@ -46,6 +47,9 @@ extern "C" {
|
||||||
int Swig_all_protected_mode() {
|
int Swig_all_protected_mode() {
|
||||||
return all_protected_mode;
|
return all_protected_mode;
|
||||||
}
|
}
|
||||||
|
void Language_replace_special_variables(String *method, String *tm, Parm *parm) {
|
||||||
|
Language::instance()->replaceSpecialVariables(method, tm, parm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some status variables used during parsing */
|
/* Some status variables used during parsing */
|
||||||
|
|
@ -323,6 +327,8 @@ directors(0) {
|
||||||
director_prot_ctor_code = 0;
|
director_prot_ctor_code = 0;
|
||||||
director_multiple_inheritance = 1;
|
director_multiple_inheritance = 1;
|
||||||
director_language = 0;
|
director_language = 0;
|
||||||
|
assert(!this_);
|
||||||
|
this_ = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Language::~Language() {
|
Language::~Language() {
|
||||||
|
|
@ -331,6 +337,7 @@ Language::~Language() {
|
||||||
Delete(enumtypes);
|
Delete(enumtypes);
|
||||||
Delete(director_ctor_code);
|
Delete(director_ctor_code);
|
||||||
Delete(none_comparison);
|
Delete(none_comparison);
|
||||||
|
this_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
|
|
@ -874,30 +881,8 @@ int Language::cDeclaration(Node *n) {
|
||||||
if (over)
|
if (over)
|
||||||
over = first_nontemplate(over);
|
over = first_nontemplate(over);
|
||||||
if (over && (over != n)) {
|
if (over && (over != n)) {
|
||||||
SwigType *tc = Copy(decl);
|
Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", Swig_name_decl(n));
|
||||||
SwigType *td = SwigType_pop_function(tc);
|
Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over), "Previous declaration is %s\n", Swig_name_decl(over));
|
||||||
String *oname;
|
|
||||||
String *cname;
|
|
||||||
if (CurrentClass) {
|
|
||||||
oname = NewStringf("%s::%s", ClassName, name);
|
|
||||||
cname = NewStringf("%s::%s", ClassName, Getattr(over, "name"));
|
|
||||||
} else {
|
|
||||||
oname = NewString(name);
|
|
||||||
cname = NewString(Getattr(over, "name"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SwigType *tc2 = Copy(Getattr(over, "decl"));
|
|
||||||
SwigType *td2 = SwigType_pop_function(tc2);
|
|
||||||
|
|
||||||
Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", SwigType_str(td, SwigType_namestr(oname)));
|
|
||||||
Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over), "Previous declaration is %s\n", SwigType_str(td2, SwigType_namestr(cname)));
|
|
||||||
|
|
||||||
Delete(tc2);
|
|
||||||
Delete(td2);
|
|
||||||
Delete(tc);
|
|
||||||
Delete(td);
|
|
||||||
Delete(oname);
|
|
||||||
Delete(cname);
|
|
||||||
return SWIG_NOWRAP;
|
return SWIG_NOWRAP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -978,7 +963,7 @@ int Language::cDeclaration(Node *n) {
|
||||||
if (Strncmp(symname, "__dummy_", 8) == 0) {
|
if (Strncmp(symname, "__dummy_", 8) == 0) {
|
||||||
SetFlag(n, "feature:ignore");
|
SetFlag(n, "feature:ignore");
|
||||||
Swig_warning(WARN_LANG_TEMPLATE_METHOD_IGNORE, input_file, line_number,
|
Swig_warning(WARN_LANG_TEMPLATE_METHOD_IGNORE, input_file, line_number,
|
||||||
"%%template() contains no name. Template method ignored: %s\n", SwigType_str(decl, SwigType_namestr(Getattr(n,"name"))));
|
"%%template() contains no name. Template method ignored: %s\n", Swig_name_decl(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!GetFlag(n, "feature:ignore"))
|
if (!GetFlag(n, "feature:ignore"))
|
||||||
|
|
@ -3423,6 +3408,24 @@ String *Language::defaultExternalRuntimeFilename() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Language::replaceSpecialVariables()
|
||||||
|
* Language modules should implement this if special variables are to be handled
|
||||||
|
* correctly in the $typemap(...) special variable macro.
|
||||||
|
* method - typemap method name
|
||||||
|
* tm - string containing typemap contents
|
||||||
|
* parm - a parameter describing the typemap type to be handled
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
void Language::replaceSpecialVariables(String *method, String *tm, Parm *parm) {
|
||||||
|
(void)method;
|
||||||
|
(void)tm;
|
||||||
|
(void)parm;
|
||||||
|
}
|
||||||
|
|
||||||
|
Language *Language::instance() {
|
||||||
|
return this_;
|
||||||
|
}
|
||||||
|
|
||||||
Hash *Language::getClassHash() const {
|
Hash *Language::getClassHash() const {
|
||||||
return classhash;
|
return classhash;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3581,17 +3581,28 @@ MODULA3():
|
||||||
Delete(throws_hash);
|
Delete(throws_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
* replaceSpecialVariables()
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
|
||||||
|
(void)method;
|
||||||
|
SwigType *type = Getattr(parm, "type");
|
||||||
|
substituteClassname(type, tm);
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* substituteClassname()
|
* substituteClassname()
|
||||||
*
|
*
|
||||||
* Substitute $m3classname with the proxy class name for classes/structs/unions that SWIG knows about.
|
* Substitute the special variable $m3classname with the proxy class name for classes/structs/unions
|
||||||
|
* that SWIG knows about.
|
||||||
* Otherwise use the $descriptor name for the Modula 3 class name. Note that the $&m3classname substitution
|
* Otherwise use the $descriptor name for the Modula 3 class name. Note that the $&m3classname substitution
|
||||||
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
|
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* pt - parameter type
|
* pt - parameter type
|
||||||
* tm - m3wraptype typemap
|
* tm - typemap contents that might contain the special variable to be replaced
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* tm - m3wraptype typemap with $m3classname substitution
|
* tm - typemap contents complete with the special variable substitution
|
||||||
* Return:
|
* Return:
|
||||||
* substitution_performed - flag indicating if a substitution was performed
|
* substitution_performed - flag indicating if a substitution was performed
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
@ -3807,7 +3818,7 @@ MODULA3():
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* typemapLookup()
|
* typemapLookup()
|
||||||
* n - for input only and must contain info for Getfile(n) and Getline(n) to work
|
* n - for input only and must contain info for Getfile(n) and Getline(n) to work
|
||||||
* op - typemap method name
|
* tmap_method - typemap method name
|
||||||
* type - typemap type to lookup
|
* type - typemap type to lookup
|
||||||
* warning - warning number to issue if no typemaps found
|
* warning - warning number to issue if no typemaps found
|
||||||
* typemap_attributes - the typemap attributes are attached to this node and will
|
* typemap_attributes - the typemap attributes are attached to this node and will
|
||||||
|
|
@ -3815,16 +3826,16 @@ MODULA3():
|
||||||
* return is never NULL, unlike Swig_typemap_lookup()
|
* return is never NULL, unlike Swig_typemap_lookup()
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
const String *typemapLookup(Node *n, const_String_or_char_ptr op, SwigType *type, int warning, Node *typemap_attributes = 0) {
|
const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
|
||||||
Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
|
Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
|
||||||
Setattr(node, "type", type);
|
Setattr(node, "type", type);
|
||||||
Setfile(node, Getfile(n));
|
Setfile(node, Getfile(n));
|
||||||
Setline(node, Getline(n));
|
Setline(node, Getline(n));
|
||||||
const String *tm = Swig_typemap_lookup(op, node, "", 0);
|
const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
|
||||||
if (!tm) {
|
if (!tm) {
|
||||||
tm = empty_string;
|
tm = empty_string;
|
||||||
if (warning != WARN_NONE)
|
if (warning != WARN_NONE)
|
||||||
Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", op, SwigType_str(type, 0));
|
Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
|
||||||
}
|
}
|
||||||
if (!typemap_attributes)
|
if (!typemap_attributes)
|
||||||
Delete(node);
|
Delete(node);
|
||||||
|
|
|
||||||
|
|
@ -718,6 +718,10 @@ String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxar
|
||||||
Parm *pi = Getattr(ni, "wrap:parms");
|
Parm *pi = Getattr(ni, "wrap:parms");
|
||||||
int num_required = emit_num_required(pi);
|
int num_required = emit_num_required(pi);
|
||||||
int num_arguments = emit_num_arguments(pi);
|
int num_arguments = emit_num_arguments(pi);
|
||||||
|
if (GetFlag(n, "wrap:this")) {
|
||||||
|
num_required++;
|
||||||
|
num_arguments++;
|
||||||
|
}
|
||||||
if (num_arguments > *maxargs)
|
if (num_arguments > *maxargs)
|
||||||
*maxargs = num_arguments;
|
*maxargs = num_arguments;
|
||||||
int varargs = emit_isvarargs(pi);
|
int varargs = emit_isvarargs(pi);
|
||||||
|
|
@ -751,7 +755,7 @@ String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxar
|
||||||
Printf(f, "}\n");
|
Printf(f, "}\n");
|
||||||
Delete(lfmt);
|
Delete(lfmt);
|
||||||
}
|
}
|
||||||
if (print_typecheck(f, j, pj)) {
|
if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj)) {
|
||||||
Printf(f, "if (_v) {\n");
|
Printf(f, "if (_v) {\n");
|
||||||
num_braces++;
|
num_braces++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -728,7 +728,7 @@ public:
|
||||||
Printf(f_shadow, tab8 tab8 "_mod = imp.load_module('%s', fp, pathname, description)\n", module);
|
Printf(f_shadow, tab8 tab8 "_mod = imp.load_module('%s', fp, pathname, description)\n", module);
|
||||||
Printv(f_shadow, tab4 tab8, "finally:\n", NULL);
|
Printv(f_shadow, tab4 tab8, "finally:\n", NULL);
|
||||||
Printv(f_shadow, tab8 tab8, "fp.close()\n", NULL);
|
Printv(f_shadow, tab8 tab8, "fp.close()\n", NULL);
|
||||||
Printv(f_shadow, tab8 tab8, "return _mod\n", NULL);
|
Printv(f_shadow, tab4 tab8, "return _mod\n", NULL);
|
||||||
Printf(f_shadow, tab4 "%s = swig_import_helper()\n", module);
|
Printf(f_shadow, tab4 "%s = swig_import_helper()\n", module);
|
||||||
Printv(f_shadow, tab4, "del swig_import_helper\n", NULL);
|
Printv(f_shadow, tab4, "del swig_import_helper\n", NULL);
|
||||||
Printv(f_shadow, "else:\n", NULL);
|
Printv(f_shadow, "else:\n", NULL);
|
||||||
|
|
|
||||||
|
|
@ -1418,15 +1418,13 @@ static List * Swig_overload_rank(Node *n,
|
||||||
String *t2 = Getattr(p2,"tmap:typecheck:precedence");
|
String *t2 = Getattr(p2,"tmap:typecheck:precedence");
|
||||||
if ((!t1) && (!nodes[i].error)) {
|
if ((!t1) && (!nodes[i].error)) {
|
||||||
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
|
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
|
||||||
"Overloaded %s(%s) not supported (no type checking rule for '%s').\n",
|
"Overloaded method %s not supported (no type checking rule for '%s').\n",
|
||||||
Getattr(nodes[i].n,"name"),ParmList_str_defaultargs(Getattr(nodes[i].n,"parms")),
|
Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
|
||||||
SwigType_str(Getattr(p1,"type"),0));
|
|
||||||
nodes[i].error = 1;
|
nodes[i].error = 1;
|
||||||
} else if ((!t2) && (!nodes[j].error)) {
|
} else if ((!t2) && (!nodes[j].error)) {
|
||||||
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
|
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
|
||||||
"Overloaded %s(%s) not supported (no type checking rule for '%s').\n",
|
"xx Overloaded method %s not supported (no type checking rule for '%s').\n",
|
||||||
Getattr(nodes[j].n,"name"),ParmList_str_defaultargs(Getattr(nodes[j].n,"parms")),
|
Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
|
||||||
SwigType_str(Getattr(p2,"type"),0));
|
|
||||||
nodes[j].error = 1;
|
nodes[j].error = 1;
|
||||||
}
|
}
|
||||||
if (t1 && t2) {
|
if (t1 && t2) {
|
||||||
|
|
@ -1556,21 +1554,15 @@ static List * Swig_overload_rank(Node *n,
|
||||||
if (!nodes[j].error) {
|
if (!nodes[j].error) {
|
||||||
if (script_lang_wrapping) {
|
if (script_lang_wrapping) {
|
||||||
Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
|
Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
|
||||||
"Overloaded %s(%s)%s is shadowed by %s(%s)%s at %s:%d.\n",
|
"Overloaded method %s is shadowed by %s at %s:%d.\n",
|
||||||
Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms),
|
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
|
||||||
SwigType_isconst(Getattr(nodes[j].n,"decl")) ? " const" : "",
|
Getfile(nodes[i].n), Getline(nodes[i].n));
|
||||||
Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms),
|
|
||||||
SwigType_isconst(Getattr(nodes[i].n,"decl")) ? " const" : "",
|
|
||||||
Getfile(nodes[i].n),Getline(nodes[i].n));
|
|
||||||
} else {
|
} else {
|
||||||
if (!Getattr(nodes[j].n, "overload:ignore"))
|
if (!Getattr(nodes[j].n, "overload:ignore"))
|
||||||
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
|
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
|
||||||
"Overloaded method %s(%s)%s ignored. Method %s(%s)%s at %s:%d used.\n",
|
"Overloaded method %s ignored. Method %s at %s:%d used.\n",
|
||||||
Getattr(nodes[j].n,"name"), ParmList_errorstr(nodes[j].parms),
|
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
|
||||||
SwigType_isconst(Getattr(nodes[j].n,"decl")) ? " const" : "",
|
Getfile(nodes[i].n), Getline(nodes[i].n));
|
||||||
Getattr(nodes[i].n,"name"), ParmList_errorstr(nodes[i].parms),
|
|
||||||
SwigType_isconst(Getattr(nodes[i].n,"decl")) ? " const" : "",
|
|
||||||
Getfile(nodes[i].n),Getline(nodes[i].n));
|
|
||||||
}
|
}
|
||||||
nodes[j].error = 1;
|
nodes[j].error = 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,7 @@ public:
|
||||||
virtual int is_assignable(Node *n); /* Is variable assignable? */
|
virtual int is_assignable(Node *n); /* Is variable assignable? */
|
||||||
virtual String *runtimeCode(); /* returns the language specific runtime code */
|
virtual String *runtimeCode(); /* returns the language specific runtime code */
|
||||||
virtual String *defaultExternalRuntimeFilename(); /* the default filename for the external runtime */
|
virtual String *defaultExternalRuntimeFilename(); /* the default filename for the external runtime */
|
||||||
|
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm); /* Language specific special variable substitutions for $typemap() */
|
||||||
|
|
||||||
/* Runtime is C++ based, so extern "C" header section */
|
/* Runtime is C++ based, so extern "C" header section */
|
||||||
void enable_cplus_runtime_mode();
|
void enable_cplus_runtime_mode();
|
||||||
|
|
@ -250,6 +251,9 @@ public:
|
||||||
/* Set overload variable templates argc and argv */
|
/* Set overload variable templates argc and argv */
|
||||||
void setOverloadResolutionTemplates(String *argc, String *argv);
|
void setOverloadResolutionTemplates(String *argc, String *argv);
|
||||||
|
|
||||||
|
/* Language instance is a singleton - get instance */
|
||||||
|
static Language* instance();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Allow multiple-input typemaps */
|
/* Allow multiple-input typemaps */
|
||||||
void allow_multiple_input(int val = 1);
|
void allow_multiple_input(int val = 1);
|
||||||
|
|
@ -307,6 +311,7 @@ private:
|
||||||
int multiinput;
|
int multiinput;
|
||||||
int cplus_runtime;
|
int cplus_runtime;
|
||||||
int directors;
|
int directors;
|
||||||
|
static Language *this_;
|
||||||
};
|
};
|
||||||
|
|
||||||
int SWIG_main(int, char **, Language *);
|
int SWIG_main(int, char **, Language *);
|
||||||
|
|
@ -347,7 +352,9 @@ void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void SWIG_typemap_lang(const char *);
|
void SWIG_typemap_lang(const char *);
|
||||||
typedef Language *(*ModuleFactory) (void);
|
typedef Language *(*ModuleFactory) (void);
|
||||||
} void Swig_register_module(const char *name, ModuleFactory fac);
|
}
|
||||||
|
|
||||||
|
void Swig_register_module(const char *name, ModuleFactory fac);
|
||||||
ModuleFactory Swig_find_module(const char *name);
|
ModuleFactory Swig_find_module(const char *name);
|
||||||
|
|
||||||
/* Utilities */
|
/* Utilities */
|
||||||
|
|
|
||||||
|
|
@ -1611,7 +1611,7 @@ String *Swig_name_decl(Node *n) {
|
||||||
qname = NewString("");
|
qname = NewString("");
|
||||||
if (qualifier && Len(qualifier) > 0)
|
if (qualifier && Len(qualifier) > 0)
|
||||||
Printf(qname, "%s::", qualifier);
|
Printf(qname, "%s::", qualifier);
|
||||||
Printf(qname, "%s", name);
|
Printf(qname, "%s", SwigType_str(name, 0));
|
||||||
|
|
||||||
decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : "");
|
decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : "");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ void Scanner_clear(Scanner * s) {
|
||||||
Clear(s->text);
|
Clear(s->text);
|
||||||
Clear(s->scanobjs);
|
Clear(s->scanobjs);
|
||||||
Delete(s->error);
|
Delete(s->error);
|
||||||
|
s->str = 0;
|
||||||
s->error = 0;
|
s->error = 0;
|
||||||
s->line = 1;
|
s->line = 1;
|
||||||
s->nexttoken = -1;
|
s->nexttoken = -1;
|
||||||
|
|
|
||||||
|
|
@ -363,19 +363,19 @@ extern int ParmList_is_compactdefargs(ParmList *p);
|
||||||
/* --- Legacy Typemap API (somewhat simplified, ha!) --- */
|
/* --- Legacy Typemap API (somewhat simplified, ha!) --- */
|
||||||
|
|
||||||
extern void Swig_typemap_init(void);
|
extern void Swig_typemap_init(void);
|
||||||
extern void Swig_typemap_register(const_String_or_char_ptr op, ParmList *pattern, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs);
|
extern void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *pattern, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs);
|
||||||
extern int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcpattern, ParmList *pattern);
|
extern int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcpattern, ParmList *pattern);
|
||||||
extern void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *pattern);
|
extern void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *pattern);
|
||||||
extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat);
|
extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat);
|
||||||
extern void Swig_typemap_clear_apply(ParmList *pattern);
|
extern void Swig_typemap_clear_apply(ParmList *pattern);
|
||||||
extern void Swig_typemap_debug(void);
|
extern void Swig_typemap_debug(void);
|
||||||
|
|
||||||
extern String *Swig_typemap_lookup(const_String_or_char_ptr op, Node *n, const_String_or_char_ptr lname, Wrapper *f);
|
extern String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f);
|
||||||
extern String *Swig_typemap_lookup_out(const_String_or_char_ptr op, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode);
|
extern String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode);
|
||||||
extern void Swig_typemap_new_scope(void);
|
extern void Swig_typemap_new_scope(void);
|
||||||
extern Hash *Swig_typemap_pop_scope(void);
|
extern Hash *Swig_typemap_pop_scope(void);
|
||||||
|
|
||||||
extern void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wrapper *f);
|
extern void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f);
|
||||||
|
|
||||||
/* --- Code fragment support --- */
|
/* --- Code fragment support --- */
|
||||||
|
|
||||||
|
|
@ -390,6 +390,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
|
||||||
extern void Wrapper_director_mode_set(int);
|
extern void Wrapper_director_mode_set(int);
|
||||||
extern void Wrapper_director_protected_mode_set(int);
|
extern void Wrapper_director_protected_mode_set(int);
|
||||||
extern void Wrapper_all_protected_mode_set(int);
|
extern void Wrapper_all_protected_mode_set(int);
|
||||||
|
extern void Language_replace_special_variables(String *method, String *tm, Parm *parm);
|
||||||
|
|
||||||
|
|
||||||
/* -- template init -- */
|
/* -- template init -- */
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ char cvsroot_typemap_c[] = "$Id$";
|
||||||
#define SWIG_DEBUG
|
#define SWIG_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void replace_embedded_typemap(String *s);
|
static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f);
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Typemaps are stored in a collection of nested hash tables. Something like
|
* Typemaps are stored in a collection of nested hash tables. Something like
|
||||||
|
|
@ -31,14 +31,24 @@ static void replace_embedded_typemap(String *s);
|
||||||
* different typemap methods. These are referenced by names such as
|
* different typemap methods. These are referenced by names such as
|
||||||
* "tmap:in", "tmap:out", "tmap:argout", and so forth.
|
* "tmap:in", "tmap:out", "tmap:argout", and so forth.
|
||||||
*
|
*
|
||||||
* The object corresponding to a specific method has the following
|
* The object corresponding to a specific typemap method has the following attributes:
|
||||||
* attributes:
|
|
||||||
*
|
*
|
||||||
* "type" - Typemap type
|
* "type" - Typemap type
|
||||||
* "pname" - Parameter name
|
* "pname" - Parameter name
|
||||||
* "code" - Typemap code
|
* "code" - Typemap code
|
||||||
* "typemap" - Descriptive text describing the actual map
|
* "typemap" - Descriptive text describing the actual map
|
||||||
* "locals" - Local variables (if any)
|
* "locals" - Local variables (if any)
|
||||||
|
* "kwargs" - Typemap attributes
|
||||||
|
*
|
||||||
|
* Example for a typemap method named "in":
|
||||||
|
* %typemap(in, warning="987:my warning", noblock=1) int &my_int (int tmp) "$1 = $input;"
|
||||||
|
*
|
||||||
|
* "type" - r.int
|
||||||
|
* "pname" - my_int
|
||||||
|
* "code" - $1 = $input;
|
||||||
|
* "typemap" - typemap(in) int &my_int
|
||||||
|
* "locals" - int tmp
|
||||||
|
* "kwargs" - warning="987:my typemap warning", foo=123
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
@ -107,29 +117,29 @@ void Swig_typemap_init() {
|
||||||
tm_scope = 0;
|
tm_scope = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String *tmop_name(const_String_or_char_ptr op) {
|
static String *typemap_method_name(const_String_or_char_ptr tmap_method) {
|
||||||
static Hash *names = 0;
|
static Hash *names = 0;
|
||||||
String *s;
|
String *s;
|
||||||
/* Due to "interesting" object-identity semantics of DOH,
|
/* Due to "interesting" object-identity semantics of DOH,
|
||||||
we have to make sure that we only intern strings without object
|
we have to make sure that we only intern strings without object
|
||||||
identity into the hash table.
|
identity into the hash table.
|
||||||
|
|
||||||
(typemap_attach_kwargs calls tmop_name several times with
|
(typemap_attach_kwargs calls typemap_method_name several times with
|
||||||
the "same" String *op (i.e., same object identity) but differing
|
the "same" String *tmap_method (i.e., same object identity) but differing
|
||||||
string values.)
|
string values.)
|
||||||
|
|
||||||
Most other callers work around this by using char* rather than
|
Most other callers work around this by using char* rather than
|
||||||
String *.
|
String *.
|
||||||
-- mkoeppe, Jun 17, 2003
|
-- mkoeppe, Jun 17, 2003
|
||||||
*/
|
*/
|
||||||
const char *op_without_object_identity = Char(op);
|
const char *method_without_object_identity = Char(tmap_method);
|
||||||
if (!names)
|
if (!names)
|
||||||
names = NewHash();
|
names = NewHash();
|
||||||
s = Getattr(names, op_without_object_identity);
|
s = Getattr(names, method_without_object_identity);
|
||||||
if (s)
|
if (s)
|
||||||
return s;
|
return s;
|
||||||
s = NewStringf("tmap:%s", op);
|
s = NewStringf("tmap:%s", tmap_method);
|
||||||
Setattr(names, op_without_object_identity, s);
|
Setattr(names, method_without_object_identity, s);
|
||||||
Delete(s);
|
Delete(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -163,21 +173,21 @@ Hash *Swig_typemap_pop_scope() {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Swig_typemap_register()
|
* Swig_typemap_register()
|
||||||
*
|
*
|
||||||
* Add a new multi-valued typemap
|
* Add a new multi-argument typemap
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) {
|
void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) {
|
||||||
Hash *tm;
|
Hash *tm;
|
||||||
Hash *tm1;
|
Hash *tm1;
|
||||||
Hash *tm2;
|
Hash *tm2;
|
||||||
Parm *np;
|
Parm *np;
|
||||||
String *tmop;
|
String *tm_method;
|
||||||
SwigType *type;
|
SwigType *type;
|
||||||
String *pname;
|
String *pname;
|
||||||
|
|
||||||
if (!parms)
|
if (!parms)
|
||||||
return;
|
return;
|
||||||
tmop = tmop_name(op);
|
tm_method = typemap_method_name(tmap_method);
|
||||||
|
|
||||||
/* Register the first type in the parameter list */
|
/* Register the first type in the parameter list */
|
||||||
|
|
||||||
|
|
@ -202,15 +212,15 @@ void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_S
|
||||||
tm = tm1;
|
tm = tm1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now see if this typemap op has been seen before */
|
/* Now see if this typemap method has been seen before */
|
||||||
tm2 = Getattr(tm, tmop);
|
tm2 = Getattr(tm, tm_method);
|
||||||
if (!tm2) {
|
if (!tm2) {
|
||||||
tm2 = NewHash();
|
tm2 = NewHash();
|
||||||
Setattr(tm, tmop, tm2);
|
Setattr(tm, tm_method, tm2);
|
||||||
Delete(tm2);
|
Delete(tm2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For a multi-valued typemap, the typemap code and information
|
/* For a multi-argument typemap, the typemap code and information
|
||||||
is really only stored in the last argument. However, to
|
is really only stored in the last argument. However, to
|
||||||
make this work, we perform a really neat trick using
|
make this work, we perform a really neat trick using
|
||||||
the typemap operator name.
|
the typemap operator name.
|
||||||
|
|
@ -237,7 +247,7 @@ void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_S
|
||||||
np = nextSibling(parms);
|
np = nextSibling(parms);
|
||||||
if (np) {
|
if (np) {
|
||||||
/* Make an entirely new operator key */
|
/* Make an entirely new operator key */
|
||||||
String *newop = NewStringf("%s-%s+%s:", op, type, pname);
|
String *newop = NewStringf("%s-%s+%s:", tmap_method, type, pname);
|
||||||
/* Now reregister on the remaining arguments */
|
/* Now reregister on the remaining arguments */
|
||||||
Swig_typemap_register(newop, np, code, locals, kwargs);
|
Swig_typemap_register(newop, np, code, locals, kwargs);
|
||||||
|
|
||||||
|
|
@ -245,7 +255,7 @@ void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_S
|
||||||
Delete(newop);
|
Delete(newop);
|
||||||
} else {
|
} else {
|
||||||
String *str = SwigType_str(type, pname);
|
String *str = SwigType_str(type, pname);
|
||||||
String *typemap = NewStringf("typemap(%s) %s", op, str);
|
String *typemap = NewStringf("typemap(%s) %s", tmap_method, str);
|
||||||
ParmList *clocals = CopyParmList(locals);
|
ParmList *clocals = CopyParmList(locals);
|
||||||
ParmList *ckwargs = CopyParmList(kwargs);
|
ParmList *ckwargs = CopyParmList(kwargs);
|
||||||
|
|
||||||
|
|
@ -294,21 +304,21 @@ static Hash *typemap_get(SwigType *type, const_String_or_char_ptr name, int scop
|
||||||
* Copy a typemap
|
* Copy a typemap
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcparms, ParmList *parms) {
|
int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcparms, ParmList *parms) {
|
||||||
Hash *tm = 0;
|
Hash *tm = 0;
|
||||||
String *tmop;
|
String *tm_method;
|
||||||
Parm *p;
|
Parm *p;
|
||||||
String *pname;
|
String *pname;
|
||||||
SwigType *ptype;
|
SwigType *ptype;
|
||||||
int ts = tm_scope;
|
int ts = tm_scope;
|
||||||
String *tmops, *newop;
|
String *tm_methods, *newop;
|
||||||
if (ParmList_len(parms) != ParmList_len(srcparms))
|
if (ParmList_len(parms) != ParmList_len(srcparms))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tmop = tmop_name(op);
|
tm_method = typemap_method_name(tmap_method);
|
||||||
while (ts >= 0) {
|
while (ts >= 0) {
|
||||||
p = srcparms;
|
p = srcparms;
|
||||||
tmops = NewString(tmop);
|
tm_methods = NewString(tm_method);
|
||||||
while (p) {
|
while (p) {
|
||||||
ptype = Getattr(p, "type");
|
ptype = Getattr(p, "type");
|
||||||
pname = Getattr(p, "name");
|
pname = Getattr(p, "name");
|
||||||
|
|
@ -318,22 +328,22 @@ int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcparms, ParmList
|
||||||
if (!tm)
|
if (!tm)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tm = Getattr(tm, tmops);
|
tm = Getattr(tm, tm_methods);
|
||||||
if (!tm)
|
if (!tm)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Got a match. Look for next typemap */
|
/* Got a match. Look for next typemap */
|
||||||
newop = NewStringf("%s-%s+%s:", tmops, ptype, pname);
|
newop = NewStringf("%s-%s+%s:", tm_methods, ptype, pname);
|
||||||
Delete(tmops);
|
Delete(tm_methods);
|
||||||
tmops = newop;
|
tm_methods = newop;
|
||||||
p = nextSibling(p);
|
p = nextSibling(p);
|
||||||
}
|
}
|
||||||
Delete(tmops);
|
Delete(tm_methods);
|
||||||
|
|
||||||
if (!p && tm) {
|
if (!p && tm) {
|
||||||
|
|
||||||
/* Got some kind of match */
|
/* Got some kind of match */
|
||||||
Swig_typemap_register(op, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs"));
|
Swig_typemap_register(tmap_method, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ts--;
|
ts--;
|
||||||
|
|
@ -346,10 +356,10 @@ int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcparms, ParmList
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Swig_typemap_clear()
|
* Swig_typemap_clear()
|
||||||
*
|
*
|
||||||
* Delete a multi-valued typemap
|
* Delete a multi-argument typemap
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *parms) {
|
void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *parms) {
|
||||||
SwigType *type;
|
SwigType *type;
|
||||||
String *name;
|
String *name;
|
||||||
Parm *p;
|
Parm *p;
|
||||||
|
|
@ -357,7 +367,7 @@ void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *parms) {
|
||||||
Hash *tm = 0;
|
Hash *tm = 0;
|
||||||
|
|
||||||
/* This might not work */
|
/* This might not work */
|
||||||
newop = NewString(op);
|
newop = NewString(tmap_method);
|
||||||
p = parms;
|
p = parms;
|
||||||
while (p) {
|
while (p) {
|
||||||
type = Getattr(p, "type");
|
type = Getattr(p, "type");
|
||||||
|
|
@ -370,7 +380,7 @@ void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *parms) {
|
||||||
Printf(newop, "-%s+%s:", type, name);
|
Printf(newop, "-%s+%s:", type, name);
|
||||||
}
|
}
|
||||||
if (tm) {
|
if (tm) {
|
||||||
tm = Getattr(tm, tmop_name(newop));
|
tm = Getattr(tm, typemap_method_name(newop));
|
||||||
if (tm) {
|
if (tm) {
|
||||||
Delattr(tm, "code");
|
Delattr(tm, "code");
|
||||||
Delattr(tm, "locals");
|
Delattr(tm, "locals");
|
||||||
|
|
@ -591,7 +601,7 @@ static SwigType *strip_arrays(SwigType *type) {
|
||||||
* that includes a 'code' attribute.
|
* that includes a 'code' attribute.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static Hash *typemap_search(const_String_or_char_ptr op, SwigType *type, const_String_or_char_ptr name, SwigType **matchtype) {
|
static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type, const_String_or_char_ptr name, SwigType **matchtype) {
|
||||||
Hash *result = 0, *tm, *tm1, *tma;
|
Hash *result = 0, *tm, *tm1, *tma;
|
||||||
Hash *backup = 0;
|
Hash *backup = 0;
|
||||||
SwigType *noarrays = 0;
|
SwigType *noarrays = 0;
|
||||||
|
|
@ -601,7 +611,7 @@ static Hash *typemap_search(const_String_or_char_ptr op, SwigType *type, const_S
|
||||||
int isarray;
|
int isarray;
|
||||||
const String *cname = 0;
|
const String *cname = 0;
|
||||||
SwigType *unstripped = 0;
|
SwigType *unstripped = 0;
|
||||||
String *tmop = tmop_name(op);
|
String *tm_method = typemap_method_name(tmap_method);
|
||||||
|
|
||||||
if ((name) && Len(name))
|
if ((name) && Len(name))
|
||||||
cname = name;
|
cname = name;
|
||||||
|
|
@ -615,7 +625,7 @@ static Hash *typemap_search(const_String_or_char_ptr op, SwigType *type, const_S
|
||||||
if (tm && cname) {
|
if (tm && cname) {
|
||||||
tm1 = Getattr(tm, cname);
|
tm1 = Getattr(tm, cname);
|
||||||
if (tm1) {
|
if (tm1) {
|
||||||
result = Getattr(tm1, tmop); /* See if there is a type-name match */
|
result = Getattr(tm1, tm_method); /* See if there is a type-name match */
|
||||||
if (result && Getattr(result, "code"))
|
if (result && Getattr(result, "code"))
|
||||||
goto ret_result;
|
goto ret_result;
|
||||||
if (result)
|
if (result)
|
||||||
|
|
@ -623,7 +633,7 @@ static Hash *typemap_search(const_String_or_char_ptr op, SwigType *type, const_S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tm) {
|
if (tm) {
|
||||||
result = Getattr(tm, tmop); /* See if there is simply a type match */
|
result = Getattr(tm, tm_method); /* See if there is simply a type match */
|
||||||
if (result && Getattr(result, "code"))
|
if (result && Getattr(result, "code"))
|
||||||
goto ret_result;
|
goto ret_result;
|
||||||
if (result)
|
if (result)
|
||||||
|
|
@ -640,7 +650,7 @@ static Hash *typemap_search(const_String_or_char_ptr op, SwigType *type, const_S
|
||||||
if (tma && cname) {
|
if (tma && cname) {
|
||||||
tm1 = Getattr(tma, cname);
|
tm1 = Getattr(tma, cname);
|
||||||
if (tm1) {
|
if (tm1) {
|
||||||
result = Getattr(tm1, tmop); /* type-name match */
|
result = Getattr(tm1, tm_method); /* type-name match */
|
||||||
if (result && Getattr(result, "code"))
|
if (result && Getattr(result, "code"))
|
||||||
goto ret_result;
|
goto ret_result;
|
||||||
if (result)
|
if (result)
|
||||||
|
|
@ -648,7 +658,7 @@ static Hash *typemap_search(const_String_or_char_ptr op, SwigType *type, const_S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tma) {
|
if (tma) {
|
||||||
result = Getattr(tma, tmop); /* type match */
|
result = Getattr(tma, tm_method); /* type match */
|
||||||
if (result && Getattr(result, "code"))
|
if (result && Getattr(result, "code"))
|
||||||
goto ret_result;
|
goto ret_result;
|
||||||
if (result)
|
if (result)
|
||||||
|
|
@ -692,13 +702,13 @@ static Hash *typemap_search(const_String_or_char_ptr op, SwigType *type, const_S
|
||||||
if (tm && cname) {
|
if (tm && cname) {
|
||||||
tm1 = Getattr(tm, cname);
|
tm1 = Getattr(tm, cname);
|
||||||
if (tm1) {
|
if (tm1) {
|
||||||
result = Getattr(tm1, tmop); /* See if there is a type-name match */
|
result = Getattr(tm1, tm_method); /* See if there is a type-name match */
|
||||||
if (result)
|
if (result)
|
||||||
goto ret_result;
|
goto ret_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tm) { /* See if there is simply a type match */
|
if (tm) { /* See if there is simply a type match */
|
||||||
result = Getattr(tm, tmop);
|
result = Getattr(tm, tm_method);
|
||||||
if (result)
|
if (result)
|
||||||
goto ret_result;
|
goto ret_result;
|
||||||
}
|
}
|
||||||
|
|
@ -735,10 +745,10 @@ ret_result:
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* typemap_search_multi()
|
* typemap_search_multi()
|
||||||
*
|
*
|
||||||
* Search for a multi-valued typemap.
|
* Search for a multi-argument typemap.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static Hash *typemap_search_multi(const_String_or_char_ptr op, ParmList *parms, int *nmatch) {
|
static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList *parms, int *nmatch) {
|
||||||
SwigType *type;
|
SwigType *type;
|
||||||
SwigType *mtype = 0;
|
SwigType *mtype = 0;
|
||||||
String *name;
|
String *name;
|
||||||
|
|
@ -753,13 +763,13 @@ static Hash *typemap_search_multi(const_String_or_char_ptr op, ParmList *parms,
|
||||||
name = Getattr(parms, "name");
|
name = Getattr(parms, "name");
|
||||||
|
|
||||||
/* Try to find a match on the first type */
|
/* Try to find a match on the first type */
|
||||||
tm = typemap_search(op, type, name, &mtype);
|
tm = typemap_search(tmap_method, type, name, &mtype);
|
||||||
if (tm) {
|
if (tm) {
|
||||||
if (mtype && SwigType_isarray(mtype)) {
|
if (mtype && SwigType_isarray(mtype)) {
|
||||||
Setattr(parms, "tmap:match", mtype);
|
Setattr(parms, "tmap:match", mtype);
|
||||||
}
|
}
|
||||||
Delete(mtype);
|
Delete(mtype);
|
||||||
newop = NewStringf("%s-%s+%s:", op, type, name);
|
newop = NewStringf("%s-%s+%s:", tmap_method, type, name);
|
||||||
tm1 = typemap_search_multi(newop, nextSibling(parms), nmatch);
|
tm1 = typemap_search_multi(newop, nextSibling(parms), nmatch);
|
||||||
if (tm1)
|
if (tm1)
|
||||||
tm = tm1;
|
tm = tm1;
|
||||||
|
|
@ -806,7 +816,7 @@ static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, Swi
|
||||||
SwigType *ftype;
|
SwigType *ftype;
|
||||||
int bare_substitution_count = 0;
|
int bare_substitution_count = 0;
|
||||||
|
|
||||||
Replaceall(s, "$typemap", "$TYPEMAP");
|
Replaceall(s, "$typemap", "$TYPEMAP"); /* workaround for $type substitution below */
|
||||||
|
|
||||||
ftype = SwigType_typedef_resolve_all(type);
|
ftype = SwigType_typedef_resolve_all(type);
|
||||||
|
|
||||||
|
|
@ -1162,16 +1172,26 @@ static void typemap_locals(DOHString * s, ParmList *l, Wrapper *f, int argnum) {
|
||||||
*
|
*
|
||||||
* Attach one or more typemaps to a node and optionally generate the typemap contents
|
* Attach one or more typemaps to a node and optionally generate the typemap contents
|
||||||
* into the wrapper.
|
* into the wrapper.
|
||||||
* op - typemap name, eg "out", "newfree"
|
*
|
||||||
* node - the node to attach the typemaps to
|
* Looks for a typemap matching the given type and name and attaches the typemap code
|
||||||
* lname - name of variable to substitute $1, $2 etc for
|
* and any typemap attributes to the provided node.
|
||||||
* f - wrapper code to generate into if non null
|
*
|
||||||
* actioncode - code to generate into f before the out typemap code, unless
|
* The node should contain the "type" and "name" attributes for the typemap match on.
|
||||||
|
* input. The typemap code and typemap attribute values are attached onto the node
|
||||||
|
* prefixed with "tmap:". For example with tmap_method="in", the typemap code can be retrieved
|
||||||
|
* with a call to Getattr(node, "tmap:in") (this is also the string returned) and the
|
||||||
|
* "noblock" attribute can be retrieved with a call to Getattr(node, "tmap:in:noblock").
|
||||||
|
*
|
||||||
|
* tmap_method - typemap method, eg "in", "out", "newfree"
|
||||||
|
* node - the node to attach the typemap and typemap attributes to
|
||||||
|
* lname - name of variable to substitute $1, $2 etc for
|
||||||
|
* f - wrapper code to generate into if non null
|
||||||
|
* actioncode - code to generate into f before the out typemap code, unless
|
||||||
* the optimal attribute is set in the out typemap in which case
|
* the optimal attribute is set in the out typemap in which case
|
||||||
* $1 in the out typemap will be replaced by the code in actioncode.
|
* $1 in the out typemap will be replaced by the code in actioncode.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
|
static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
|
||||||
SwigType *type;
|
SwigType *type;
|
||||||
SwigType *mtype = 0;
|
SwigType *mtype = 0;
|
||||||
String *pname;
|
String *pname;
|
||||||
|
|
@ -1184,14 +1204,14 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
String *symname;
|
String *symname;
|
||||||
String *cname = 0;
|
String *cname = 0;
|
||||||
String *clname = 0;
|
String *clname = 0;
|
||||||
char *cop = Char(op);
|
char *cop = Char(tmap_method);
|
||||||
int optimal_attribute = 0;
|
int optimal_attribute = 0;
|
||||||
int optimal_substitution = 0;
|
int optimal_substitution = 0;
|
||||||
int num_substitutions = 0;
|
int num_substitutions = 0;
|
||||||
|
|
||||||
/* special case, we need to check for 'ref' call
|
/* special case, we need to check for 'ref' call
|
||||||
and set the default code 'sdef' */
|
and set the default code 'sdef' */
|
||||||
if (node && Cmp(op, "newfree") == 0) {
|
if (node && Cmp(tmap_method, "newfree") == 0) {
|
||||||
sdef = Swig_ref_call(node, lname);
|
sdef = Swig_ref_call(node, lname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1214,7 +1234,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
String *qsn = st ? Swig_symbol_string_qualify(pname, st) : 0;
|
String *qsn = st ? Swig_symbol_string_qualify(pname, st) : 0;
|
||||||
if (qsn) {
|
if (qsn) {
|
||||||
if (Len(qsn) && !Equal(qsn, pname)) {
|
if (Len(qsn) && !Equal(qsn, pname)) {
|
||||||
tm = typemap_search(op, type, qsn, &mtype);
|
tm = typemap_search(tmap_method, type, qsn, &mtype);
|
||||||
if (tm && (!Getattr(tm, "pname") || strstr(Char(Getattr(tm, "type")), "SWIGTYPE"))) {
|
if (tm && (!Getattr(tm, "pname") || strstr(Char(Getattr(tm, "type")), "SWIGTYPE"))) {
|
||||||
tm = 0;
|
tm = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1224,7 +1244,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
}
|
}
|
||||||
if (!tm)
|
if (!tm)
|
||||||
#endif
|
#endif
|
||||||
tm = typemap_search(op, type, pname, &mtype);
|
tm = typemap_search(tmap_method, type, pname, &mtype);
|
||||||
if (!tm)
|
if (!tm)
|
||||||
return sdef;
|
return sdef;
|
||||||
|
|
||||||
|
|
@ -1242,15 +1262,15 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
kw = Getattr(tm, "kwargs");
|
kw = Getattr(tm, "kwargs");
|
||||||
while (kw) {
|
while (kw) {
|
||||||
String *value = Copy(Getattr(kw, "value"));
|
String *value = Copy(Getattr(kw, "value"));
|
||||||
String *type = Getattr(kw, "type");
|
String *kwtype = Getattr(kw, "type");
|
||||||
char *ckwname = Char(Getattr(kw, "name"));
|
char *ckwname = Char(Getattr(kw, "name"));
|
||||||
if (type) {
|
if (kwtype) {
|
||||||
String *mangle = Swig_string_mangle(type);
|
String *mangle = Swig_string_mangle(kwtype);
|
||||||
Append(value, mangle);
|
Append(value, mangle);
|
||||||
Delete(mangle);
|
Delete(mangle);
|
||||||
}
|
}
|
||||||
sprintf(temp, "%s:%s", cop, ckwname);
|
sprintf(temp, "%s:%s", cop, ckwname);
|
||||||
Setattr(node, tmop_name(temp), value);
|
Setattr(node, typemap_method_name(temp), value);
|
||||||
if (Cmp(temp, "out:optimal") == 0)
|
if (Cmp(temp, "out:optimal") == 0)
|
||||||
optimal_attribute = (Cmp(value, "0") != 0) ? 1 : 0;
|
optimal_attribute = (Cmp(value, "0") != 0) ? 1 : 0;
|
||||||
Delete(value);
|
Delete(value);
|
||||||
|
|
@ -1324,7 +1344,13 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
if (locals && f) {
|
if (locals && f) {
|
||||||
typemap_locals(s, locals, f, -1);
|
typemap_locals(s, locals, f, -1);
|
||||||
}
|
}
|
||||||
replace_embedded_typemap(s);
|
|
||||||
|
{
|
||||||
|
ParmList *parm_sublist = NewParm(type, pname);
|
||||||
|
Setattr(parm_sublist, "lname", lname);
|
||||||
|
replace_embedded_typemap(s, parm_sublist, f);
|
||||||
|
Delete(parm_sublist);
|
||||||
|
}
|
||||||
|
|
||||||
Replace(s, "$name", pname, DOH_REPLACE_ANY);
|
Replace(s, "$name", pname, DOH_REPLACE_ANY);
|
||||||
|
|
||||||
|
|
@ -1333,23 +1359,23 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
Replace(s, "$symname", symname, DOH_REPLACE_ANY);
|
Replace(s, "$symname", symname, DOH_REPLACE_ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
Setattr(node, tmop_name(op), s);
|
Setattr(node, typemap_method_name(tmap_method), s);
|
||||||
if (locals) {
|
if (locals) {
|
||||||
sprintf(temp, "%s:locals", cop);
|
sprintf(temp, "%s:locals", cop);
|
||||||
Setattr(node, tmop_name(temp), locals);
|
Setattr(node, typemap_method_name(temp), locals);
|
||||||
Delete(locals);
|
Delete(locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Checkattr(tm, "type", "SWIGTYPE")) {
|
if (Checkattr(tm, "type", "SWIGTYPE")) {
|
||||||
sprintf(temp, "%s:SWIGTYPE", cop);
|
sprintf(temp, "%s:SWIGTYPE", cop);
|
||||||
Setattr(node, tmop_name(temp), "1");
|
Setattr(node, typemap_method_name(temp), "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for warnings */
|
/* Look for warnings */
|
||||||
{
|
{
|
||||||
String *w;
|
String *w;
|
||||||
sprintf(temp, "%s:warning", cop);
|
sprintf(temp, "%s:warning", cop);
|
||||||
w = Getattr(node, tmop_name(temp));
|
w = Getattr(node, typemap_method_name(temp));
|
||||||
if (w) {
|
if (w) {
|
||||||
Swig_warning(0, Getfile(node), Getline(node), "%s\n", w);
|
Swig_warning(0, Getfile(node), Getline(node), "%s\n", w);
|
||||||
}
|
}
|
||||||
|
|
@ -1357,11 +1383,11 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
|
|
||||||
/* Look for code fragments */
|
/* Look for code fragments */
|
||||||
{
|
{
|
||||||
String *f;
|
String *fragment;
|
||||||
sprintf(temp, "%s:fragment", cop);
|
sprintf(temp, "%s:fragment", cop);
|
||||||
f = Getattr(node, tmop_name(temp));
|
fragment = Getattr(node, typemap_method_name(temp));
|
||||||
if (f) {
|
if (fragment) {
|
||||||
String *fname = Copy(f);
|
String *fname = Copy(fragment);
|
||||||
Setfile(fname, Getfile(node));
|
Setfile(fname, Getfile(node));
|
||||||
Setline(fname, Getline(node));
|
Setline(fname, Getline(node));
|
||||||
Swig_fragment_emit(fname);
|
Swig_fragment_emit(fname);
|
||||||
|
|
@ -1382,14 +1408,14 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
String *Swig_typemap_lookup_out(const_String_or_char_ptr op, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
|
String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
|
||||||
assert(actioncode);
|
assert(actioncode);
|
||||||
assert(Cmp(op, "out") == 0);
|
assert(Cmp(tmap_method, "out") == 0);
|
||||||
return Swig_typemap_lookup_impl(op, node, lname, f, actioncode);
|
return Swig_typemap_lookup_impl(tmap_method, node, lname, f, actioncode);
|
||||||
}
|
}
|
||||||
|
|
||||||
String *Swig_typemap_lookup(const_String_or_char_ptr op, Node *node, const_String_or_char_ptr lname, Wrapper *f) {
|
String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f) {
|
||||||
return Swig_typemap_lookup_impl(op, node, lname, f, 0);
|
return Swig_typemap_lookup_impl(tmap_method, node, lname, f, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
@ -1403,7 +1429,7 @@ String *Swig_typemap_lookup(const_String_or_char_ptr op, Node *node, const_Strin
|
||||||
* A new attribute called "tmap:in:foo" with value "xyz" is attached to p.
|
* A new attribute called "tmap:in:foo" with value "xyz" is attached to p.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr op, Parm *p) {
|
static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method, Parm *p) {
|
||||||
String *temp = NewStringEmpty();
|
String *temp = NewStringEmpty();
|
||||||
Parm *kw = Getattr(tm, "kwargs");
|
Parm *kw = Getattr(tm, "kwargs");
|
||||||
while (kw) {
|
while (kw) {
|
||||||
|
|
@ -1417,36 +1443,36 @@ static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr op, Parm *p
|
||||||
value = v;
|
value = v;
|
||||||
}
|
}
|
||||||
Clear(temp);
|
Clear(temp);
|
||||||
Printf(temp, "%s:%s", op, Getattr(kw, "name"));
|
Printf(temp, "%s:%s", tmap_method, Getattr(kw, "name"));
|
||||||
Setattr(p, tmop_name(temp), value);
|
Setattr(p, typemap_method_name(temp), value);
|
||||||
Delete(value);
|
Delete(value);
|
||||||
kw = nextSibling(kw);
|
kw = nextSibling(kw);
|
||||||
}
|
}
|
||||||
Clear(temp);
|
Clear(temp);
|
||||||
Printf(temp, "%s:match_type", op);
|
Printf(temp, "%s:match_type", tmap_method);
|
||||||
Setattr(p, tmop_name(temp), Getattr(tm, "type"));
|
Setattr(p, typemap_method_name(temp), Getattr(tm, "type"));
|
||||||
Delete(temp);
|
Delete(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* typemap_warn()
|
* typemap_warn()
|
||||||
*
|
*
|
||||||
* If any warning message is attached to this parameter's "tmap:op:warning"
|
* If any warning message is attached to this parameter's "tmap:<method>:warning"
|
||||||
* attribute, print that warning message.
|
* attribute, print that warning message.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void typemap_warn(const_String_or_char_ptr op, Parm *p) {
|
static void typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) {
|
||||||
String *temp = NewStringf("%s:warning", op);
|
String *temp = NewStringf("%s:warning", tmap_method);
|
||||||
String *w = Getattr(p, tmop_name(temp));
|
String *w = Getattr(p, typemap_method_name(temp));
|
||||||
Delete(temp);
|
Delete(temp);
|
||||||
if (w) {
|
if (w) {
|
||||||
Swig_warning(0, Getfile(p), Getline(p), "%s\n", w);
|
Swig_warning(0, Getfile(p), Getline(p), "%s\n", w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void typemap_emit_code_fragments(const_String_or_char_ptr op, Parm *p) {
|
static void typemap_emit_code_fragments(const_String_or_char_ptr tmap_method, Parm *p) {
|
||||||
String *temp = NewStringf("%s:fragment", op);
|
String *temp = NewStringf("%s:fragment", tmap_method);
|
||||||
String *f = Getattr(p, tmop_name(temp));
|
String *f = Getattr(p, typemap_method_name(temp));
|
||||||
if (f) {
|
if (f) {
|
||||||
String *fname = Copy(f);
|
String *fname = Copy(f);
|
||||||
Setfile(fname, Getfile(p));
|
Setfile(fname, Getfile(p));
|
||||||
|
|
@ -1457,13 +1483,6 @@ static void typemap_emit_code_fragments(const_String_or_char_ptr op, Parm *p) {
|
||||||
Delete(temp);
|
Delete(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
|
||||||
* Swig_typemap_attach_parms()
|
|
||||||
*
|
|
||||||
* Given a parameter list, this function attaches all of the typemaps for a
|
|
||||||
* given typemap type
|
|
||||||
* ----------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
|
static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
|
||||||
Parm *kw = Getattr(tm, "kwargs");
|
Parm *kw = Getattr(tm, "kwargs");
|
||||||
while (kw) {
|
while (kw) {
|
||||||
|
|
@ -1476,7 +1495,23 @@ static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wrapper *f) {
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Swig_typemap_attach_parms()
|
||||||
|
*
|
||||||
|
* Given a parameter list, this function attaches all of the typemaps and typemap
|
||||||
|
* attributes to the parameter for each type in the parameter list.
|
||||||
|
*
|
||||||
|
* This function basically provides the typemap code and typemap attribute values as
|
||||||
|
* attributes on each parameter prefixed with "tmap:". For example with tmap_method="in", the typemap
|
||||||
|
* code can be retrieved for the first parameter with a call to Getattr(parm, "tmap:in")
|
||||||
|
* and the "numinputs" attribute can be retrieved with a call to Getattr(parm, "tmap:in:numinputs").
|
||||||
|
*
|
||||||
|
* tmap_method - typemap method, eg "in", "out", "newfree"
|
||||||
|
* parms - parameter list to attach each typemap and all typemap attributes
|
||||||
|
* f - wrapper code to generate into if non null
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f) {
|
||||||
Parm *p, *firstp;
|
Parm *p, *firstp;
|
||||||
Hash *tm;
|
Hash *tm;
|
||||||
int nmatch = 0;
|
int nmatch = 0;
|
||||||
|
|
@ -1485,21 +1520,21 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra
|
||||||
ParmList *locals;
|
ParmList *locals;
|
||||||
int argnum = 0;
|
int argnum = 0;
|
||||||
char temp[256];
|
char temp[256];
|
||||||
char *cop = Char(op);
|
char *cop = Char(tmap_method);
|
||||||
String *kwmatch = 0;
|
String *kwmatch = 0;
|
||||||
p = parms;
|
p = parms;
|
||||||
|
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stdout, "Swig_typemap_attach_parms: %s\n", op);
|
Printf(stdout, "Swig_typemap_attach_parms: %s\n", tmap_method);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (p) {
|
while (p) {
|
||||||
argnum++;
|
argnum++;
|
||||||
nmatch = 0;
|
nmatch = 0;
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stdout, "parms: %s %s %s\n", op, Getattr(p, "name"), Getattr(p, "type"));
|
Printf(stdout, "parms: %s %s %s\n", tmap_method, Getattr(p, "name"), Getattr(p, "type"));
|
||||||
#endif
|
#endif
|
||||||
tm = typemap_search_multi(op, p, &nmatch);
|
tm = typemap_search_multi(tmap_method, p, &nmatch);
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
if (tm)
|
if (tm)
|
||||||
Printf(stdout, "found: %s\n", tm);
|
Printf(stdout, "found: %s\n", tm);
|
||||||
|
|
@ -1605,7 +1640,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra
|
||||||
|
|
||||||
if (Checkattr(tm, "type", "SWIGTYPE")) {
|
if (Checkattr(tm, "type", "SWIGTYPE")) {
|
||||||
sprintf(temp, "%s:SWIGTYPE", cop);
|
sprintf(temp, "%s:SWIGTYPE", cop);
|
||||||
Setattr(p, tmop_name(temp), "1");
|
Setattr(p, typemap_method_name(temp), "1");
|
||||||
}
|
}
|
||||||
p = nextSibling(p);
|
p = nextSibling(p);
|
||||||
}
|
}
|
||||||
|
|
@ -1614,7 +1649,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra
|
||||||
typemap_locals(s, locals, f, argnum);
|
typemap_locals(s, locals, f, argnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
replace_embedded_typemap(s);
|
replace_embedded_typemap(s, firstp, f);
|
||||||
|
|
||||||
/* Replace the argument number */
|
/* Replace the argument number */
|
||||||
sprintf(temp, "%d", argnum);
|
sprintf(temp, "%d", argnum);
|
||||||
|
|
@ -1622,34 +1657,34 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra
|
||||||
|
|
||||||
/* Attach attributes to object */
|
/* Attach attributes to object */
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), s);
|
Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), s);
|
||||||
#endif
|
#endif
|
||||||
Setattr(firstp, tmop_name(op), s); /* Code object */
|
Setattr(firstp, typemap_method_name(tmap_method), s); /* Code object */
|
||||||
|
|
||||||
if (locals) {
|
if (locals) {
|
||||||
sprintf(temp, "%s:locals", cop);
|
sprintf(temp, "%s:locals", cop);
|
||||||
Setattr(firstp, tmop_name(temp), locals);
|
Setattr(firstp, typemap_method_name(temp), locals);
|
||||||
Delete(locals);
|
Delete(locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach a link to the next parameter. Needed for multimaps */
|
/* Attach a link to the next parameter. Needed for multimaps */
|
||||||
sprintf(temp, "%s:next", cop);
|
sprintf(temp, "%s:next", cop);
|
||||||
Setattr(firstp, tmop_name(temp), p);
|
Setattr(firstp, typemap_method_name(temp), p);
|
||||||
|
|
||||||
/* Attach kwargs */
|
/* Attach kwargs */
|
||||||
typemap_attach_kwargs(tm, op, firstp);
|
typemap_attach_kwargs(tm, tmap_method, firstp);
|
||||||
|
|
||||||
/* Print warnings, if any */
|
/* Print warnings, if any */
|
||||||
typemap_warn(op, firstp);
|
typemap_warn(tmap_method, firstp);
|
||||||
|
|
||||||
/* Look for code fragments */
|
/* Look for code fragments */
|
||||||
typemap_emit_code_fragments(op, firstp);
|
typemap_emit_code_fragments(tmap_method, firstp);
|
||||||
|
|
||||||
/* increase argnum to consider numinputs */
|
/* increase argnum to consider numinputs */
|
||||||
argnum += nmatch - 1;
|
argnum += nmatch - 1;
|
||||||
Delete(s);
|
Delete(s);
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), Getattr(firstp, tmop_name(op)));
|
Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), Getattr(firstp, typemap_method_name(tmap_method)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1659,23 +1694,8 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
|
||||||
* split_embedded()
|
|
||||||
*
|
|
||||||
* This function replaces the special variable $typemap(....) with typemap
|
|
||||||
* code. The general form of $typemap is as follows:
|
|
||||||
*
|
|
||||||
* $TYPEMAP(method, $var1=value, $var2=value, $var3=value,...)
|
|
||||||
*
|
|
||||||
* For example:
|
|
||||||
*
|
|
||||||
* $TYPEMAP(in, $1=int x, $input=y, ...)
|
|
||||||
*
|
|
||||||
* Note: this was added as an experiment and could be removed
|
|
||||||
* ----------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* Splits the arguments of an embedded typemap */
|
/* Splits the arguments of an embedded typemap */
|
||||||
static List *split_embedded(String *s) {
|
static List *split_embedded_typemap(String *s) {
|
||||||
List *args = 0;
|
List *args = 0;
|
||||||
char *c, *start;
|
char *c, *start;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
|
|
@ -1683,6 +1703,7 @@ static List *split_embedded(String *s) {
|
||||||
args = NewList();
|
args = NewList();
|
||||||
|
|
||||||
c = strchr(Char(s), '(');
|
c = strchr(Char(s), '(');
|
||||||
|
assert(c);
|
||||||
c++;
|
c++;
|
||||||
|
|
||||||
start = c;
|
start = c;
|
||||||
|
|
@ -1723,41 +1744,36 @@ static List *split_embedded(String *s) {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void split_var(String *s, String **name, String **value) {
|
/* -----------------------------------------------------------------------------
|
||||||
char *eq;
|
* replace_embedded_typemap()
|
||||||
char *c;
|
*
|
||||||
|
* This function replaces the special variable macro $typemap(...) with typemap
|
||||||
|
* code. The general form of $typemap is as follows:
|
||||||
|
*
|
||||||
|
* $typemap(method, typelist, var1=value, var2=value, ...)
|
||||||
|
*
|
||||||
|
* where varx parameters are optional and undocumented; they were used in an earlier version of $typemap.
|
||||||
|
* A search is made using the typemap matching rules of form:
|
||||||
|
*
|
||||||
|
* %typemap(method) typelist {...}
|
||||||
|
*
|
||||||
|
* and if found will substitute in the typemap contents, making appropriate variable replacements.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* $typemap(in, int) # simple usage matching %typemap(in) int { ... }
|
||||||
|
* $typemap(in, int b) # simple usage matching %typemap(in) int b { ... } or above %typemap
|
||||||
|
* $typemap(in, (Foo<int, bool> a, int b)) # multi-argument typemap matching %typemap(in) (Foo<int, bool> a, int b) {...}
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
eq = strchr(Char(s), '=');
|
static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f) {
|
||||||
if (!eq) {
|
|
||||||
*name = 0;
|
|
||||||
*value = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
c = Char(s);
|
|
||||||
*name = NewStringWithSize(c, eq - c);
|
|
||||||
|
|
||||||
/* Look for $n variables */
|
|
||||||
if (isdigit((int) *(c))) {
|
|
||||||
/* Parse the value as a type */
|
|
||||||
String *v;
|
|
||||||
Parm *p;
|
|
||||||
v = NewString(eq + 1);
|
|
||||||
p = Swig_cparse_parm(v);
|
|
||||||
Delete(v);
|
|
||||||
*value = p;
|
|
||||||
} else {
|
|
||||||
*value = NewString(eq + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void replace_embedded_typemap(String *s) {
|
|
||||||
char *start = 0;
|
char *start = 0;
|
||||||
while ((start = strstr(Char(s), "$TYPEMAP("))) {
|
while ((start = strstr(Char(s), "$TYPEMAP("))) { /* note $typemap capitalisation to $TYPEMAP hack */
|
||||||
|
|
||||||
/* Gather the argument */
|
/* Gather the parameters */
|
||||||
char *end = 0, *c;
|
char *end = 0, *c;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
String *tmp;
|
String *dollar_typemap;
|
||||||
|
int syntax_error = 1;
|
||||||
c = start;
|
c = start;
|
||||||
while (*c) {
|
while (*c) {
|
||||||
if (*c == '(')
|
if (*c == '(')
|
||||||
|
|
@ -1772,103 +1788,127 @@ static void replace_embedded_typemap(String *s) {
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
if (end) {
|
if (end) {
|
||||||
tmp = NewStringWithSize(start, (end - start));
|
dollar_typemap = NewStringWithSize(start, (end - start));
|
||||||
|
syntax_error = 0;
|
||||||
} else {
|
} else {
|
||||||
tmp = 0;
|
dollar_typemap = NewStringWithSize(start, (c - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Got a substitution. Split it apart into pieces */
|
if (!syntax_error) {
|
||||||
if (tmp) {
|
|
||||||
List *l;
|
List *l;
|
||||||
|
String *tmap_method;
|
||||||
Hash *vars;
|
Hash *vars;
|
||||||
String *method;
|
syntax_error = 1;
|
||||||
int i, ilen;
|
|
||||||
|
|
||||||
l = split_embedded(tmp);
|
/* Split apart each parameter in $typemap(...) */
|
||||||
vars = NewHash();
|
l = split_embedded_typemap(dollar_typemap);
|
||||||
ilen = Len(l);
|
|
||||||
for (i = 1; i < ilen; i++) {
|
|
||||||
String *n, *v;
|
|
||||||
split_var(Getitem(l, i), &n, &v);
|
|
||||||
if (n && v) {
|
|
||||||
Insert(n, 0, "$");
|
|
||||||
Setattr(vars, n, v);
|
|
||||||
}
|
|
||||||
Delete(n);
|
|
||||||
Delete(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
method = Getitem(l, 0);
|
if (Len(l) >= 2) {
|
||||||
/* Generate the parameter list for matching typemaps */
|
ParmList *to_match_parms;
|
||||||
|
tmap_method = Getitem(l, 0);
|
||||||
|
|
||||||
{
|
/* the second parameter might contain multiple sub-parameters for multi-argument
|
||||||
Parm *p = 0;
|
* typemap matching, so split these parameters apart */
|
||||||
Parm *first = 0;
|
to_match_parms = Swig_cparse_parms(Getitem(l, 1));
|
||||||
char temp[32];
|
if (to_match_parms) {
|
||||||
int n = 1;
|
Parm *p = to_match_parms;
|
||||||
while (1) {
|
Parm *sub_p = parm_sublist;
|
||||||
Hash *v;
|
String *empty_string = NewStringEmpty();
|
||||||
sprintf(temp, "$%d", n);
|
String *lname = empty_string;
|
||||||
v = Getattr(vars, temp);
|
while (p) {
|
||||||
if (v) {
|
if (sub_p) {
|
||||||
if (p) {
|
lname = Getattr(sub_p, "lname");
|
||||||
set_nextSibling(p, v);
|
sub_p = nextSibling(sub_p);
|
||||||
set_previousSibling(v, p);
|
|
||||||
}
|
}
|
||||||
p = v;
|
Setattr(p, "lname", lname);
|
||||||
Setattr(p, "lname", Getattr(p, "name"));
|
p = nextSibling(p);
|
||||||
if (Getattr(p, "value")) {
|
|
||||||
Setattr(p, "name", Getattr(p, "value"));
|
|
||||||
}
|
|
||||||
if (!first)
|
|
||||||
first = p;
|
|
||||||
DohIncref(p);
|
|
||||||
Delattr(vars, temp);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
n++;
|
Delete(empty_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* process optional extra parameters - the variable replacements (undocumented) */
|
||||||
|
vars = NewHash();
|
||||||
|
{
|
||||||
|
int i, ilen;
|
||||||
|
ilen = Len(l);
|
||||||
|
for (i = 2; i < ilen; i++) {
|
||||||
|
String *parm = Getitem(l, i);
|
||||||
|
char *eq = strchr(Char(parm), '=');
|
||||||
|
char *c = Char(parm);
|
||||||
|
if (eq && (eq - c > 0)) {
|
||||||
|
String *name = NewStringWithSize(c, eq - c);
|
||||||
|
String *value = NewString(eq + 1);
|
||||||
|
Insert(name, 0, "$");
|
||||||
|
Setattr(vars, name, value);
|
||||||
|
} else {
|
||||||
|
to_match_parms = 0; /* error - variable replacement parameters must be of form varname=value */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Perform a typemap search */
|
/* Perform a typemap search */
|
||||||
if (first) {
|
if (to_match_parms) {
|
||||||
|
static int already_substituting = 0;
|
||||||
|
String *tm;
|
||||||
|
String *attr;
|
||||||
|
int match = 0;
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stdout, "Swig_typemap_attach_parms: embedded\n");
|
Printf(stdout, "Swig_typemap_attach_parms: embedded\n");
|
||||||
#endif
|
#endif
|
||||||
Swig_typemap_attach_parms(method, first, 0);
|
if (!already_substituting) {
|
||||||
{
|
already_substituting = 1;
|
||||||
String *tm;
|
Swig_typemap_attach_parms(tmap_method, to_match_parms, f);
|
||||||
int match = 0;
|
already_substituting = 0;
|
||||||
char attr[64];
|
|
||||||
sprintf(attr, "tmap:%s", Char(method));
|
|
||||||
|
|
||||||
/* Look for the typemap code */
|
/* Look for the typemap code */
|
||||||
tm = Getattr(first, attr);
|
attr = NewStringf("tmap:%s", tmap_method);
|
||||||
|
tm = Getattr(to_match_parms, attr);
|
||||||
if (tm) {
|
if (tm) {
|
||||||
sprintf(attr, "tmap:%s:next", Char(method));
|
Printf(attr, "%s", ":next");
|
||||||
if (!Getattr(first, attr)) {
|
/* fail if multi-argument lookup requested in $typemap(...) and the lookup failed */
|
||||||
/* Should be no more matches. Hack??? */
|
if (!Getattr(to_match_parms, attr)) {
|
||||||
/* Replace all of the remaining variables */
|
/* Replace parameter variables */
|
||||||
Iterator ki;
|
Iterator ki;
|
||||||
for (ki = First(vars); ki.key; ki = Next(ki)) {
|
for (ki = First(vars); ki.key; ki = Next(ki)) {
|
||||||
Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY);
|
Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY);
|
||||||
}
|
}
|
||||||
/* Do the replacement */
|
/* offer the target language module the chance to make special variable substitutions */
|
||||||
Replace(s, tmp, tm, DOH_REPLACE_ANY);
|
Language_replace_special_variables(tmap_method, tm, to_match_parms);
|
||||||
|
/* finish up - do the substitution */
|
||||||
|
Replace(s, dollar_typemap, tm, DOH_REPLACE_ANY);
|
||||||
Delete(tm);
|
Delete(tm);
|
||||||
match = 1;
|
match = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", tmp);
|
String *dtypemap = NewString(dollar_typemap);
|
||||||
|
Replaceall(dtypemap, "$TYPEMAP", "$typemap");
|
||||||
|
Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", dtypemap);
|
||||||
|
Delete(dtypemap);
|
||||||
}
|
}
|
||||||
|
Delete(attr);
|
||||||
|
} else {
|
||||||
|
/* simple recursive call check, but prevents using an embedded typemap that contains another embedded typemap */
|
||||||
|
String *dtypemap = NewString(dollar_typemap);
|
||||||
|
Replaceall(dtypemap, "$TYPEMAP", "$typemap");
|
||||||
|
Swig_error(Getfile(s), Getline(s), "Recursive $typemap calls not supported - %s\n", dtypemap);
|
||||||
|
Delete(dtypemap);
|
||||||
}
|
}
|
||||||
|
syntax_error = 0;
|
||||||
}
|
}
|
||||||
|
Delete(vars);
|
||||||
}
|
}
|
||||||
Replace(s, tmp, "<embedded typemap>", DOH_REPLACE_ANY);
|
|
||||||
Delete(vars);
|
|
||||||
Delete(tmp);
|
|
||||||
Delete(l);
|
Delete(l);
|
||||||
}
|
}
|
||||||
|
if (syntax_error) {
|
||||||
|
String *dtypemap = NewString(dollar_typemap);
|
||||||
|
Replaceall(dtypemap, "$TYPEMAP", "$typemap");
|
||||||
|
Swig_error(Getfile(s), Getline(s), "Syntax error in: %s\n", dtypemap);
|
||||||
|
Delete(dtypemap);
|
||||||
|
}
|
||||||
|
Replace(s, dollar_typemap, "<error in embedded typemap>", DOH_REPLACE_ANY);
|
||||||
|
Delete(dollar_typemap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue