mirror of https://github.com/swig/swig
1280 lines
36 KiB
HTML
1280 lines
36 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>SWIG and PHP</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff">
|
|
<H1><a name="Php">32 SWIG and PHP</a></H1>
|
|
<!-- INDEX -->
|
|
<div class="sectiontoc">
|
|
<ul>
|
|
<li><a href="#Php_nn1">Generating PHP Extensions</a>
|
|
<ul>
|
|
<li><a href="#Php_nn1_1">Building a loadable extension</a>
|
|
<li><a href="#Php_nn1_3">Using PHP Extensions</a>
|
|
</ul>
|
|
<li><a href="#Php_nn2">Basic PHP interface</a>
|
|
<ul>
|
|
<li><a href="#Php_nn2_1">Constants</a>
|
|
<li><a href="#Php_nn2_2">Global Variables</a>
|
|
<li><a href="#Php_nn2_3">Functions</a>
|
|
<li><a href="#Php_nn2_4">Overloading</a>
|
|
<li><a href="#Php_nn2_5">Pointers and References</a>
|
|
<li><a href="#Php_nn2_6">Structures and C++ classes</a>
|
|
<ul>
|
|
<li><a href="#Php_nn2_6_1">Using -noproxy</a>
|
|
<li><a href="#Php_nn2_6_2">Constructors and Destructors</a>
|
|
<li><a href="#Php_nn2_6_3">Static Member Variables</a>
|
|
<li><a href="#Php_nn2_6_4">Static Member Functions</a>
|
|
<li><a href="#Php_nn2_6_5">Specifying Implemented Interfaces</a>
|
|
</ul>
|
|
<li><a href="#Php_nn2_7">PHP Pragmas, Startup and Shutdown code</a>
|
|
</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>
|
|
</div>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
<p>
|
|
In this chapter, we discuss SWIG's support of PHP. SWIG currently supports
|
|
generating wrappers for PHP7 and PHP8. Support for PHP5 was removed in SWIG
|
|
4.0.0 and support for PHP4 was removed in SWIG 1.3.37.
|
|
</p>
|
|
|
|
<p>
|
|
Currently any PHP7 or PHP8 release should work.
|
|
</p>
|
|
|
|
<p>
|
|
In order to use this module, you will need to have a copy of the PHP
|
|
include files to compile the SWIG generated files. If you installed
|
|
PHP from a binary package, you may need to install a "php-dev" or "php-devel"
|
|
package for these to be installed. You can find out where these files are
|
|
by running <tt>php-config --includes</tt>. To use the built PHP module you
|
|
will need either the php binary or the Apache php module. If you want to build
|
|
your extension into php directly, you will need the complete PHP source tree
|
|
available.
|
|
</p>
|
|
|
|
<H2><a name="Php_nn1">32.1 Generating PHP Extensions</a></H2>
|
|
|
|
|
|
<p>
|
|
To build a PHP extension, run swig using the <tt>-php7</tt> option as follows
|
|
(<tt>-php</tt> is also supported and currently is an alias for <tt>-php7</tt>
|
|
but prior to SWIG 4.0.0 it was an alias for <tt>-php5</tt>):
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
swig -php7 example.i
|
|
</pre></div>
|
|
|
|
<p>
|
|
This will produce 3 files example_wrap.c, php_example.h and
|
|
example.php. The first file, <tt>example_wrap.c</tt> contains all of
|
|
the C code needed to build a PHP extension. The second file,
|
|
<tt>php_example.h</tt> contains the header information needed if
|
|
you wish to statically link the extension into the php interpreter.
|
|
The third file,
|
|
<tt>example.php</tt> can be included by PHP scripts. It attempts to
|
|
dynamically load the extension and contains extra php code specified
|
|
in the interface file. If wrapping C++ code with PHP classes, it will
|
|
also contain PHP class wrappers.
|
|
</p>
|
|
|
|
<p>
|
|
SWIG can generate PHP extensions from C++ libraries as well when
|
|
given the <tt>-c++</tt> option. The support for C++ is discussed in
|
|
more detail in <a href="#Php_nn2_6">section 27.2.6</a>. The generated
|
|
C++ wrapper will be called example_wrap.cxx. You can specify a
|
|
different extension for the C++ wrapper using <tt>-cppext</tt> -
|
|
e.g. if you want example_wrap.cc use <tt>-cppext cc</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
The usual (and recommended) way is to build the extension as a separate
|
|
dynamically loaded module (which is supported by all modern operating
|
|
systems).
|
|
</p>
|
|
|
|
<p>
|
|
It is also possible to rebuild PHP from source so that your module is
|
|
statically linked into the php executable/library. This is a lot more
|
|
work, and also requires a full rebuild of PHP to update your module,
|
|
and it doesn't play nicely with package system. We don't recommend
|
|
this approach, or provide explicit support for it.
|
|
</p>
|
|
|
|
<H3><a name="Php_nn1_1">32.1.1 Building a loadable extension</a></H3>
|
|
|
|
|
|
<p>
|
|
To build your module as a dynamically loadable extension, use compilation
|
|
commands like these (if you aren't using GCC, the commands will be different,
|
|
and there may be some variation between platforms - these commands should at
|
|
least work for Linux though):
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
gcc `php-config --includes` -fpic -c example_wrap.c example.c
|
|
gcc -shared example_wrap.o example.o -o example.so
|
|
</pre></div>
|
|
|
|
<H3><a name="Php_nn1_3">32.1.2 Using PHP Extensions</a></H3>
|
|
|
|
|
|
<p>
|
|
To test the extension from a PHP script, you first need to tell PHP to
|
|
load it. To do this, add a line like this to the <tt>[PHP]</tt> section of
|
|
<tt>php.ini</tt>:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
extension=/path/to/modulename.so
|
|
</pre></div>
|
|
|
|
<p>
|
|
If the module is in PHP's default extension directory, you can omit the path.
|
|
</p>
|
|
|
|
<p>
|
|
For some SAPIs (for example, the CLI SAPI) you can instead use the
|
|
<a href="https://www.php.net/manual/en/function.dl.php">dl() function</a> to load
|
|
an extension at run time, by adding a line like this to the start of each
|
|
PHP script which uses your extension:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
dl("/path/to/modulename.so"); // Load the module
|
|
</pre></div>
|
|
|
|
<p>
|
|
But note that <tt>dl()</tt> isn't supported when running PHP through a
|
|
webserver - you'll need to use <tt>extension</tt> in <tt>php.ini</tt> as
|
|
described above.
|
|
</p>
|
|
|
|
<p>
|
|
The PHP module which SWIG generates will also attempt to do the <tt>dl()</tt>
|
|
call for you if the extension isn't already loaded:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
include("example.php");
|
|
</pre></div>
|
|
|
|
<p>
|
|
This PHP module also defines the PHP classes for the wrapped API, so you'll
|
|
almost certainly want to include it anyway.
|
|
</p>
|
|
|
|
<H2><a name="Php_nn2">32.2 Basic PHP interface</a></H2>
|
|
|
|
|
|
<p>
|
|
It is important to understand that PHP uses a single global namespace
|
|
into which all symbols from extension modules are loaded. It is quite
|
|
possible for names of symbols in one extension module to clash with
|
|
other symbols unless care is taken to <tt>%rename</tt> them. At present
|
|
SWIG doesn't have support for generating wrappers which make use of PHP's
|
|
namespace feature.
|
|
</p>
|
|
|
|
<H3><a name="Php_nn2_1">32.2.1 Constants</a></H3>
|
|
|
|
|
|
<p>
|
|
These work in much the same way as in C/C++. Constants can be defined
|
|
by using either the normal C pre-processor declarations, or the
|
|
<tt>%constant</tt> SWIG directive. These will then be available from
|
|
your PHP script as a PHP constant, (i.e. no dollar sign is needed to
|
|
access them.) For example, with a swig interface file like this,
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
|
|
#define PI 3.14159
|
|
|
|
%constant int E = 2.71828
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
you can access the constants in your PHP script like this,
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
include("example.php");
|
|
|
|
echo "PI = " . PI . "\n";
|
|
|
|
echo "E = " . E . "\n";
|
|
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
There's one peculiarity of how constants work in PHP which it is useful
|
|
to note (this is not specific to SWIG though) - if you try to use an undeclared
|
|
constant, PHP will emit a warning (or a notice in PHP 7.1 and earlier) and then
|
|
expand the constant to a string version of the constant's name. Unfortunately
|
|
it is easy to miss the warning message if you're using PHP in a webserver as
|
|
it will probably end up in error.log or similar. Apparently this will throw
|
|
an Error in a future version of PHP, but until then it's something to be
|
|
aware of.
|
|
</p>
|
|
|
|
<p>
|
|
For example,
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
|
|
#define EASY_TO_MISPELL 0
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
accessed incorrectly in PHP,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
include("example.php");
|
|
|
|
if(EASY_TO_MISPEL) {
|
|
...
|
|
} else {
|
|
...
|
|
}
|
|
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The mis-spelled constant will become the string 'EASY_TO_MISPEL', which
|
|
is treated as true by the if test, when the value of the intended constant
|
|
would be treated as false!
|
|
</p>
|
|
|
|
<H3><a name="Php_nn2_2">32.2.2 Global Variables</a></H3>
|
|
|
|
|
|
<p>
|
|
Because PHP does not provide a mechanism to intercept access and
|
|
assignment of global variables, global variables are supported through
|
|
the use of automatically generated accessor functions.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example;
|
|
|
|
%inline %{
|
|
double seki = 2;
|
|
void print_seki() {
|
|
zend_printf("seki is now %f\n", seki);
|
|
}
|
|
%}
|
|
</pre></div>
|
|
|
|
<p>
|
|
is accessed as follows:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
include("example.php");
|
|
print seki_get();
|
|
seki_set( seki_get() * 2); # The C variable is now 4.
|
|
print seki_get();
|
|
</pre></div>
|
|
|
|
<p>
|
|
SWIG supports global variables of all C datatypes including pointers
|
|
and complex objects. To support additional types, you just need to
|
|
supply the standard <tt>in</tt> and <tt>out</tt> typemaps, which get
|
|
used because of the wrapping as <tt>_get()</tt> and <tt>_set()</tt>
|
|
functions.
|
|
</p>
|
|
|
|
<p>
|
|
SWIG honors the <tt>%immutable</tt> modifier by not generating code
|
|
for the <tt>_set</tt> method. This provides read-only access to the
|
|
variable from the php script. Attempting to access the <tt>_set</tt>
|
|
method will result in a php fatal error because the function is
|
|
undefined.
|
|
</p>
|
|
|
|
<p>
|
|
At this time SWIG does not support custom accessor methods.
|
|
</p>
|
|
|
|
<H3><a name="Php_nn2_3">32.2.3 Functions</a></H3>
|
|
|
|
|
|
<p>
|
|
C functions are converted into PHP functions. Default/optional arguments are
|
|
also allowed. An interface file like this :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
int foo(int a);
|
|
double bar(double, double b = 3.0);
|
|
...
|
|
</pre></div>
|
|
|
|
<p>
|
|
Will be accessed in PHP like this :
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
include("example.php");
|
|
$a = foo(2);
|
|
$b = bar(3.5, -1.5);
|
|
$c = bar(3.5); # Use default argument for 2nd parameter
|
|
|
|
</pre></div>
|
|
|
|
<!-- This isn't correct for 1.3.30 and needs rewriting to reflect reality
|
|
<p>
|
|
Because PHP is a dynamically typed language, the default typemaps
|
|
used for simple types will attempt to coerce the arguments into the appropriate type. That is the following invocations are equivalent:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
$a = foo(2);
|
|
$a = foo("2");
|
|
$a = foo(2.0);
|
|
</pre></div>
|
|
|
|
<p>
|
|
Functions are invoked using pass by value semantics like all of PHP.
|
|
This means the conversion which automatically takes place when
|
|
invoking a swig wrapped method does not change the native type of the
|
|
argument variable.
|
|
</p>
|
|
<div class="code"><pre>
|
|
$s = "2 A string representing two";
|
|
$a = foo($s); # invokes 'foo(2)';
|
|
print $s; # The value of $s was not changed.
|
|
</pre></div>
|
|
-->
|
|
|
|
|
|
<H3><a name="Php_nn2_4">32.2.4 Overloading</a></H3>
|
|
|
|
|
|
<p>
|
|
Although PHP does not support overloading functions natively, swig
|
|
will generate dispatch functions which will use <tt>%typecheck</tt>
|
|
typemaps to allow overloading. This dispatch function's operation and
|
|
precedence is described in <a
|
|
href="SWIGPlus.html#SWIGPlus_overloaded_methods">Overloaded functions and methods</a>.
|
|
</p>
|
|
|
|
<!-- This isn't correct for 1.3.30 and needs rewriting to reflect reality
|
|
<p>
|
|
Because PHP is a dynamically typed language, simple values can be
|
|
silently converted from one type to another. For example, integers,
|
|
doubles and strings silently convert to each other depending on
|
|
context. This situation make overloading slightly problematic because
|
|
given the following function:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
void doit( int i );
|
|
void doit( double i );
|
|
</pre></div>
|
|
|
|
<p>
|
|
it is questionable which to invoke when <tt>doit("2");</tt> is used in
|
|
PHP. The string <tt>"2"</tt> simultaneously represents the integer
|
|
<tt>2</tt> and the double <tt>2.0</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
In order to provide the most natural experience to PHP programmers,
|
|
the default <tt>%typecheck</tt> implemented in <tt>php.swg</tt>
|
|
allows any simple type (integer, double, string) in PHP to be used for
|
|
any simple C type (int, double, char *). The function selected then
|
|
depends only on the argument type precedence defined by SWIG.
|
|
</p>
|
|
|
|
<p>
|
|
It should be noted that <tt>SWIGTYPE</tt> references and pointers will
|
|
not be silently converted. So these two functions:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
void doit( const Vector & );
|
|
void doit( int i );
|
|
</pre></div>
|
|
|
|
<p>
|
|
Cause less confusion and <tt>doit("2");</tt> will invoke the function
|
|
taking the integer argument.
|
|
</p>
|
|
-->
|
|
|
|
<H3><a name="Php_nn2_5">32.2.5 Pointers and References</a></H3>
|
|
|
|
|
|
<p>
|
|
Pointers to C/C++ objects are represented
|
|
as PHP resources, rather like MySQL connection handles.
|
|
</p>
|
|
|
|
<p>
|
|
There are multiple ways to wrap pointers to simple types. Given the
|
|
following C method:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
void add( int *in1, int *in2, int *result);
|
|
</pre></div>
|
|
|
|
<p>
|
|
One can include <b>cpointer.i</b> to generate PHP wrappers to <tt>int
|
|
*</tt>.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
%include "cpointer.i"
|
|
%pointer_functions(int, intp)
|
|
|
|
void add( int *in1, int *in2, int *result);
|
|
</pre></div>
|
|
|
|
<p>
|
|
This will result in the following usage in PHP:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
<?php
|
|
|
|
include("example.php");
|
|
|
|
$in1=copy_intp(3);
|
|
$in2=copy_intp(5);
|
|
$result=new_intp();
|
|
|
|
add( $in1, $in2, $result );
|
|
|
|
echo "The sum " . intp_value($in1) . " + " . intp_value($in2) . " = " . intp_value( $result) . "\n";
|
|
</pre></div>
|
|
|
|
<p>
|
|
An alternative would be to use the include <b>typemaps.i</b> which
|
|
defines named typemaps for INPUT, OUTPUT and INOUT variables. One
|
|
needs to either <tt>%apply</tt> the appropriate typemap or adjust the
|
|
parameter names as appropriate.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
%include "typemaps.i"
|
|
|
|
void add( int *INPUT, int *INPUT, int *OUTPUT);
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
This will result in the following usage in PHP:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
<?php
|
|
|
|
include("example.php");
|
|
|
|
$in1 = 3;
|
|
$in2 = 5;
|
|
$result= add($in1, $in2); # Note using variables for the input is unnecessary.
|
|
|
|
echo "The sum $in1 + $in2 = $result\n";
|
|
</pre></div>
|
|
|
|
<p>
|
|
Because PHP has a native concept of reference, it may seem more natural
|
|
to the PHP developer to use references to pass pointers. To enable
|
|
this, one needs to include <b>phppointers.i</b> which defines the
|
|
named typemap REF.
|
|
</p>
|
|
|
|
<p>
|
|
In case you write your own typemaps, SWIG supports an attribute called
|
|
<tt>byref</tt>: if you set that, then SWIG will make sure that the generated
|
|
wrapper function will want the input parameter as a reference.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
%include "phppointers.i"
|
|
|
|
void add( int *REF, int *REF, int *REF);
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
This will result in the following usage in PHP:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
<?php
|
|
|
|
include("example.php");
|
|
|
|
$in1 = 3;
|
|
$in2 = 5;
|
|
$result = 0;
|
|
add($in1, $in2, $result);
|
|
|
|
echo "The sum $in1 + $in2 = $result\n";
|
|
</pre></div>
|
|
|
|
<p>
|
|
It is important to note that a php variable which is NULL when passed
|
|
by reference would end up passing a NULL pointer into the function.
|
|
In PHP, an unassigned variable (i.e. where the first reference to the
|
|
variable is not an assignment) is
|
|
NULL. In the above example, if any of the three variables had not
|
|
been assigned, a NULL pointer would have been passed into
|
|
<tt>add</tt>. Depending on the implementation of the function, this
|
|
may or may not be a good thing.
|
|
</p>
|
|
|
|
<p>
|
|
We chose to allow passing NULL pointers into functions because that is
|
|
sometimes required in C libraries. A NULL pointer can be created in
|
|
PHP in a number of ways: by using <tt>unset</tt> on an existing
|
|
variable, or assigning <tt>NULL</tt> to a variable.
|
|
</p>
|
|
|
|
<H3><a name="Php_nn2_6">32.2.6 Structures and C++ classes</a></H3>
|
|
|
|
|
|
<p>
|
|
SWIG defaults to wrapping C++ structs and classes with PHP classes - this
|
|
is done by generating a PHP wrapper script which defines proxy classes
|
|
which calls a set of flat functions which actually wrap the C++ class.
|
|
You can disable this wrapper layer by passing the command-line option
|
|
"-noproxy" in which case you'll just get the flat functions.
|
|
</p>
|
|
|
|
<p>
|
|
This interface file
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module vector
|
|
|
|
class Vector {
|
|
public:
|
|
double x, y, z;
|
|
Vector();
|
|
~Vector();
|
|
double magnitude();
|
|
};
|
|
|
|
struct Complex {
|
|
double re, im;
|
|
};
|
|
</pre></div>
|
|
|
|
<p>
|
|
Would be used in the following way from PHP:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
<?php
|
|
require "vector.php";
|
|
|
|
$v = new Vector();
|
|
$v->x = 3;
|
|
$v->y = 4;
|
|
$v->z = 5;
|
|
|
|
echo "Magnitude of ($v->x, $v->y, $v->z) = " . $v->magnitude() . "\n";
|
|
|
|
$v = NULL; # destructor called.
|
|
|
|
$c = new Complex();
|
|
|
|
$c->re = 0;
|
|
$c->im = 0;
|
|
|
|
# $c destructor called when $c goes out of scope.
|
|
</pre></div>
|
|
|
|
<p>
|
|
Member variables and methods are accessed using the <tt>-></tt> operator.
|
|
</p>
|
|
|
|
<H4><a name="Php_nn2_6_1">32.2.6.1 Using -noproxy</a></H4>
|
|
|
|
|
|
<p>
|
|
The <tt>-noproxy</tt> option flattens the object structure and
|
|
generates collections of named functions (these are the functions
|
|
which the PHP class wrappers call). The above example results
|
|
in the following PHP functions:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
new_Vector();
|
|
Vector_x_set($obj, $d);
|
|
Vector_x_get($obj);
|
|
Vector_y_set($obj, $d);
|
|
Vector_y_get($obj);
|
|
Vector_z_set($obj, $d);
|
|
Vector_z_get($obj);
|
|
Vector_magnitude($obj);
|
|
new_Complex();
|
|
Complex_re_set($obj, $d);
|
|
Complex_re_get($obj);
|
|
Complex_im_set($obj, $d);
|
|
Complex_im_get($obj);
|
|
</pre></div>
|
|
|
|
<H4><a name="Php_nn2_6_2">32.2.6.2 Constructors and Destructors</a></H4>
|
|
|
|
|
|
<p>
|
|
The constructor is called when <tt>new Object()</tt> (or
|
|
<tt>new_Object()</tt> if using <tt>-noproxy</tt>) is used to create an
|
|
instance of the object. If multiple constructors are defined for an
|
|
object, function overloading will be used to determine which
|
|
constructor to execute.
|
|
</p>
|
|
|
|
<p>
|
|
Because PHP uses reference counting to manage resources, simple
|
|
assignment of one variable to another such as:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
$ref = $v;
|
|
</pre></div>
|
|
|
|
<p>
|
|
causes the symbol <tt>$ref</tt> to refer to the same underlying object
|
|
as <tt>$v</tt>. This does not result in a call to the C++ copy
|
|
constructor or copy assignment operator.
|
|
</p>
|
|
|
|
<p>
|
|
One can force execution of the copy constructor by using:
|
|
</p>
|
|
<div class="code"><pre>
|
|
$o_copy = new Object($o);
|
|
</pre></div>
|
|
|
|
<p>
|
|
Destructors are automatically called when all variables referencing
|
|
the instance are reassigned or go out of scope. The destructor is not
|
|
available to be called manually. To force a destructor to be called
|
|
the programmer can either reassign the variable or call
|
|
<tt>unset($v)</tt>
|
|
</p>
|
|
|
|
<H4><a name="Php_nn2_6_3">32.2.6.3 Static Member Variables</a></H4>
|
|
|
|
|
|
<p>
|
|
Static member variables in C++ are not wrapped as such in PHP
|
|
as it does not appear to be possible to intercept accesses to such variables.
|
|
Therefore, static member variables are
|
|
wrapped using a class function with the same name, which
|
|
returns the current value of the class variable. For example
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
|
|
class Ko {
|
|
static int threats;
|
|
};
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
would be accessed in PHP as,
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
include("example.php");
|
|
|
|
echo "There have now been " . Ko::threats() . " threats\n";
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
To set the static member variable, pass the value as the argument to the class
|
|
function, e.g.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
|
|
Ko::threats(10);
|
|
|
|
echo "There have now been " . Ko::threats() . " threats\n";
|
|
|
|
</pre></div>
|
|
<H4><a name="Php_nn2_6_4">32.2.6.4 Static Member Functions</a></H4>
|
|
|
|
|
|
<p>
|
|
Static member functions are supported in PHP using the
|
|
<tt>class::function()</tt> syntax. For example
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
class Ko {
|
|
static void threats();
|
|
};
|
|
</pre></div>
|
|
|
|
would be executed in PHP as,
|
|
<div class="code"><pre>
|
|
include("example.php");
|
|
Ko::threats();
|
|
</pre></div>
|
|
|
|
|
|
<H4><a name="Php_nn2_6_5">32.2.6.5 Specifying Implemented Interfaces</a></H4>
|
|
|
|
|
|
<p>
|
|
PHP supports the concept of abstract interfaces which a class can implement.
|
|
Since SWIG 3.0.3, you can tell SWIG that a wrapped class (for example
|
|
<code>MyIterator</code>) implements the <code>Iterator</code> interface like
|
|
so:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%typemap("phpinterfaces") MyIterator "Iterator";
|
|
</pre></div>
|
|
|
|
<p>
|
|
If there are multiple interfaces, just list them separated by commas.
|
|
</p>
|
|
|
|
<H3><a name="Php_nn2_7">32.2.7 PHP Pragmas, Startup and Shutdown code</a></H3>
|
|
|
|
|
|
<p>
|
|
To place PHP code in the generated "example.php" file one can use the
|
|
<b>code</b> pragma. The code is inserted after loading the shared
|
|
object.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
%pragma(php) code="
|
|
# This code is inserted into example.php
|
|
echo \"example.php execution\\n\";
|
|
"
|
|
</pre></div>
|
|
|
|
<p>
|
|
Results in the following in "example.php"
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
# This code is inserted into example.php
|
|
echo "example.php execution\n";
|
|
</pre></div>
|
|
|
|
<p>
|
|
The <b>version</b> pragma can be used to add version to generated PHP extension module. The version is inserted in the zend_module_entry block.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
%pragma(php) version="1.5"
|
|
</pre></div>
|
|
|
|
<p>
|
|
The <b>include</b> pragma is a short cut to add include statements to
|
|
the example.php file.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example
|
|
%pragma(php) code="
|
|
include \"include.php\";
|
|
"
|
|
%pragma(php) include="include.php" // equivalent.
|
|
</pre></div>
|
|
|
|
<p>
|
|
The <b>phpinfo</b> pragma inserts code in the
|
|
<tt>PHP_MINFO_FUNCTION</tt> which is called from PHP's
|
|
phpinfo() function.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example;
|
|
%pragma(php) phpinfo="
|
|
zend_printf("An example of PHP support through SWIG\n");
|
|
php_info_print_table_start();
|
|
php_info_print_table_header(2, \"Directive\", \"Value\");
|
|
php_info_print_table_row(2, \"Example support\", \"enabled\");
|
|
php_info_print_table_end();
|
|
"
|
|
</pre></div>
|
|
|
|
<p>
|
|
To insert code into the <tt>PHP_MINIT_FUNCTION</tt>, one can use
|
|
either <tt>%init</tt> or <tt>%minit</tt>.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example;
|
|
%init {
|
|
zend_printf("Inserted into PHP_MINIT_FUNCTION\n");
|
|
}
|
|
%minit {
|
|
zend_printf("Inserted into PHP_MINIT_FUNCTION\n");
|
|
}
|
|
</pre></div>
|
|
|
|
<p>
|
|
To insert code into the <tt>PHP_MSHUTDOWN_FUNCTION</tt>, one can use
|
|
either <tt>%shutdown</tt> or <tt>%mshutdown</tt>.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module example;
|
|
%mshutdown {
|
|
zend_printf("Inserted into PHP_MSHUTDOWN_FUNCTION\n");
|
|
}
|
|
</pre></div>
|
|
|
|
<p>
|
|
The <tt>%rinit</tt> and <tt>%rshutdown</tt> statements are very similar but insert code
|
|
into the request init (PHP_RINIT_FUNCTION) and request shutdown (PHP_RSHUTDOWN_FUNCTION) code respectively.
|
|
</p>
|
|
|
|
<H2><a name="Php_nn3">32.3 Cross language polymorphism</a></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">32.3.1 Enabling directors</a></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 the virtual methods in class Foo
|
|
%feature("director") Foo;
|
|
</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 the 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">32.3.2 Director classes</a></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 <tt>struct swig_object_wrapper</tt>
|
|
which is used to implement 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).
|
|
Virtual methods that have a final specifier are unsurprisingly excluded.
|
|
Thus the 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 stores it
|
|
in the <tt>struct swig_object_wrapper</tt>. This is true whether or not
|
|
directors are enabled for the particular class in question. However
|
|
when a class <i>derived</i> from a proxy class is created, SWIG instead
|
|
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">32.3.3 Ownership and object destruction</a></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">32.3.4 Exception unrolling</a></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, an
|
|
exception thrown in PHP code called from C++ causes the PHP interpreter
|
|
to flag that an exception is thrown, then return passes to C++ as if
|
|
the PHP function had returned <code>Null</code>. Assuming the directorout
|
|
typemaps handle this (those SWIG defines by default should) then once
|
|
control returns to PHP code again, the PHP exception will actually propagate.
|
|
</p>
|
|
|
|
<p>
|
|
Sometimes this control flow is problematic, and you want to skip any
|
|
handling in the C++ code. To achieve this, it is necessary
|
|
to temporarily translate the PHP exception into a C++ exception. This can be
|
|
achieved using the %feature("director:except") directive. The following code
|
|
should suffice in most cases:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%feature("director:except") {
|
|
#if SWIG_VERSION >= 0x040100
|
|
if ($error != NULL)
|
|
#else
|
|
if ($error == FAILURE)
|
|
#endif
|
|
{
|
|
throw Swig::DirectorMethodException();
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If you only need to support SWIG >= 4.1.0, you can just use the
|
|
<tt>($error != NULL)</tt> condition.
|
|
</p>
|
|
|
|
<p>
|
|
In SWIG 4.1.0, <tt>$error</tt> was changed in the SWIG/PHP director
|
|
implementation to make it work more like how it does for other languages.
|
|
Previously, <tt>$error</tt> didn't actually indicate an exception, but instead
|
|
was only set to <tt>FAILURE</tt> if there was a problem calling the PHP method.
|
|
Now <tt>$error</tt> indicates if the PHP method threw a PHP exception, and
|
|
directorout typemaps for PHP no longer need to be gated by <tt>if (EG(exception))</tt>.
|
|
</p>
|
|
|
|
<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">32.3.5 Overhead and code bloat</a></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">32.3.6 Typemaps</a></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">32.3.7 Miscellaneous</a></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>
|
|
</html>
|