1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
<h1>Calling PHP functions</h1>
<p>
Let's get one thing clear first. Running native code is much faster than
running PHP code. So, once your C++ function or your C++ method finally
gets called, you normally cast the parameters to native variables, and
you start running your own fast algorithm. And you don't want to call
other PHP functions from that moment on.
</p>
<p>
If, however, you would like to make a call to a PHP function - whether that
is a function that is built-in in the Zend engine, that is defined in an
extension, or even a function that comes from PHP user space - you can do
so.
</p>
<p>
<pre class="language-c++"><code>#include <phpcpp.h>
#include <iostream>
/**
* Native function that is callable from PHP
*
* This function gets two parameters: an associative array and a callback.
* It does not do anything meaningful, it is just a demonstration function.
*
* @param params The parameters passed to the function
*/
void example_function(Php::Parameters &params)
{
// first parameter is an array
Php::Value array = params[0];
// call the PHP array_keys() function to get the parameter keys
std::vector<std::string> keys = Php::array_keys(array);
// loop through the keys
for (auto &key : keys)
{
// output key
Php::out << "key: " << key << std::endl;
}
// call a function from user space
Php::Value data = Php::call("some_function", "some_parameter");
// create an object (this will also call __construct())
Php::Object time("DateTime", "now");
// call a method on the datetime object
Php::out << time.call("format", "Y-m-d H:i:s") << std::endl;
// second parameter is a callback function
Php::Value callback = params[1];
// call the callback function
callback("some","parameter");
// in PHP it is possible to create an array with two parameters, the first
// parameter being an object, and the second parameter should be the name
// of the method, we can do that in PHP-CPP too
Php::Array time_format({time, "format"});
// call the method that is stored in the array
Php::out << time_format("Y-m-d H:i:s") << std::endl;
}
/**
* Switch to C context, because the Zend engine expects get get_module()
* to have a C style function signature
*/
extern "C" {
/**
* Startup function that is automatically called by the Zend engine
* when PHP starts, and that should return the extension details
* @return void*
*/
PHPCPP_EXPORT void *get_module()
{
// the extension object
static Php::Extension extension("my_extension", "1.0");
// add the example function so that it can be called from PHP scripts
extension.add("example_function", example_function);
// return the extension details
return extension;
}
}</code></pre>
</p>
<p>
In above example you can see quite some different ways to call PHP
functions from C++. The first one is the call to Php::array_keys(). The
PHP-CPP internally has a long list of all important PHP functions, and
you can call these functions directly from your extension. Php::array_keys()
is one of them.
</p>
<p>
Many of the built-in function functions (like Php::array_keys()) return a
Php::Value object. In the example however, you saw that we assigned the
return value directly to a std::vector. This works because the Php::Value
object has an implicit casting operator to automatically transform the
object to a vector.
</p>
<p>
Not every PHP function can of course be called like the built-in functions
can. User space functions, or functions from optional PHP extensions are not
automatically forwarded by the PHP-CPP library. Such functions can still be
called by using the Php::call() function. You must supply the name of the
function to call, and an optional list of arguments.
</p>
<p>
The Php::Object class (which is derived from Php::Value) can be used to
create objects, and implicitly call the __construct() method. To call a
method on an object, you can use the Php::Value::call() method, which
is used in the example to call the PHP method DateTime::format().
</p>
<p>
In PHP scripts you can create an array with two members: an object and
the name of a method. This array can then be used as if it was a regular
function. You can do similar things in C++, as we showed in the example with the
"time_format" variable.
</p>
<p>
The following script runs the example.
</p>
<p>
<pre class="language-php"><code>
<?php
// define a user space function
function some_function($param)
{
echo("userspace function called with $param\n");
}
// example input
$input = array(
'x' => 10,
'y' => 20,
'z' => 30
);
example_function($input, function($param1, $param2) {
echo("lambda function called with param $param1 $param2\n");
});
?></code></pre>
</p>
<p>
This above script will generate output similar to this:
<p>
<pre>
key: x
key: y
key: z
userspace function called with some_parameter
2014-03-08 13:55:54
lambda function called with param some parameter
2014-03-08 13:55:54
</pre>
</p>
<p>
If you call a function or a method that does not exist, a Php::Exception
will be thrown. If you do not catch this exception in your C++ code, it
will bubble up and appear in PHP user space.
</p>
|