From 9390addb0798598d7b333dcc86487caf0117a231 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Fri, 16 Jan 2015 13:40:49 +0100 Subject: added documentation about lambda functions --- documentation/lambda-functions.html | 208 ++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 documentation/lambda-functions.html (limited to 'documentation') diff --git a/documentation/lambda-functions.html b/documentation/lambda-functions.html new file mode 100644 index 0000000..19b7775 --- /dev/null +++ b/documentation/lambda-functions.html @@ -0,0 +1,208 @@ +

Lambda functions

+

+ C++ and PHP both support lambda functions or anonumous functions (in + the C++ world the word 'lambda' is most used, PHP people speak about + 'anonymous functions'). With PHP-CPP you can pass these functions + from one language to the other. It is possible to call an anonymous + PHP function from your C++ code, and the other way around, to call a C++ + lambda from a PHP script. +

+

Calling anonymous PHP functions from C++

+

+ Let's start with a very simple example in PHP. In PHP you can create + anonymous functions, and assign them to a variable (or pass them + directly to a function). +

+

+

<php
+// anonymous PHP function stored in the variable $f
+$f = function($a, $b) {
+    
+    // return the sum of the parameters
+    return $a + $b;
+}
+
+// pass the function to another function
+other_function($f);
+
+// or pass an anonymous function without assigning it to a variable
+other_function(function() {
+    
+    // return the product of the parameters
+    return $a * $b;
+});
+
+?>
+
+

+

+ The code above should be familiar to most PHP programmers. The + 'other_function' can of course be implemented in PHP user space, + but to demonstrate how to do this with PHP-CPP we are going to + build it with C++. Just like all the other functions that you've + seen in the earlier examples, such a C++ function function receives + a vector of Php::Value objects as its parameters. +

+

+

#include <phpcpp.h>
+/**
+ *  Native function that is callable from PHP
+ *
+ *  This function gets one parameter that holds a callable anonynous
+ *  PHP function.
+ *
+ *  @param  params      The parameters passed to the function
+ */
+void other_function(Php::Parameters &params)
+{
+    // first parameter is an anonymous function
+    Php::Value func = params[0];
+    
+    // the Php::Value class has implemented the operator (), which allows
+    // us to use the object just as if it is a real function.
+    Php::Value result = func(3, 4);
+    
+    // @todo do something with the result
+}
+
+/**
+ *  Switch to C context, because the Zend engine expects the 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("other_function", other_function);
+        
+        // return the extension details
+        return extension;
+    }
+}
+

+

+ It is that simple. But the other way around is possible too. Imagine + we have a function in PHP user space code that accepts a function + as it's parameter: +

+

+

<php
+// function that iterates over an array, and calls a function on every
+// element in that array, it returns a new array with every item
+// replaced by the result of the callback
+function my_iterate($array, $callback) {
+    
+    // initial result variable
+    $result = array();
+    
+    // loop through the array
+    foreach ($array as $index => $item) {
+        
+        // call the callback on the item
+        $result[$index] = $callback($item);
+    }
+    
+    // done
+    return $result;
+}
+<?>
+
+

+

+ Imagine that we want to call this PHP function from your C++ code, + using a C++ lambda function as a callback. This is possible, and easy: +

+

+

#include <phpcpp.h>
+/**
+ *  Native function that is callable from PHP
+ */
+void run_test()
+{
+    // create the anonymous function
+    Php::Function multiply_by_two([](Php::Parameters &params) -> Php::Value) {
+        
+        // make sure the function was really called with one parameter
+        if (params.size() == 0) return nullptr;
+        
+        // one parameter is passed to the function
+        Php::Value param = params[0];
+        
+        // multiple the parameter by two
+        return params * 2;
+    });
+
+    // the function now is callable
+    Php::Value four = multiply_by_two(2);
+    
+    // a Php::Function object is a derived Php::Value, and can be used
+    // as a normal Php::Value object - it just happen to store a callback,
+    // it can also be stored in a Php::Value object, without losing
+    // anything
+    Php::Value value = multiply_by_two;
+    
+    // the value object now also holds a function
+    Php::Value six = value(3);
+    
+    // create an array
+    Php::Value array;
+    array[0] = 1;
+    array[1] = 2;
+    array[2] = 3;
+    array[3] = 4;
+    
+    // call the user-space function
+    Php::Value result = Php::call("my_iterate", array, multiply_by_two);
+    
+    // @todo do something with the result variable (which now holds
+    // an array with values 2, 4, 6 and 8).
+}
+
+/**
+ *  Switch to C context, because the Zend engine expects the 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("run_test", run_test);
+        
+        // return the extension details
+        return extension;
+    }
+}
+

+

+ In the example we assigned a C++ lambda function to a Php::Function + object. The Php::Function class is derived from the Php::Value class. + The only difference between a Php::Value and a Php::Function is + that the constructor of Php::Function accepts a function as its + parameter. Despite that difference, both classes are completely + identical. In fact, we would have preferred to make it possible to + assign C++ functions directly to Php::Value objects, but that was + impossible because of calling ambiguities. +

+

+ The Php::Function class can be used as if it is a normal Php::Value + object: you can assign it to other Php::Value objects, and you + can use it as a parameter when you call user space PHP functions. + In the above example we do exactly that: we call the user space + my_iterate() function with our own 'multiply_by_two' C++ function. +

-- cgit v1.2.3