Writing PHP Extensions – Part 4 Function Arguments

See Part 3 Here

Just like most other languages, you can pass arguments to your extension functions either by value or by reference. By default, all arguments are assumed to be passed by value. We introduce two more PHP-CPP classes now:

 

Php::ByVal and Php::ByRef

A ByVal argument passed to a function only has local scope inside the function. Whatever manipulation is done to the data within the function does not affect its value outside the function from where it was called because the compiler makes a copy of the data and sends it to the function rather than send the actual data.

A ByRef argument has scope outside the function even after the function has finished executing. That means if the argument data is changed within the function, when the control returns to the calling code, the data will contain the changed value instead of the value which was passed into the function.

The compiler sends the original data into the function for a ByRef argument so its new value is available after the function has finished executing.

Function arguments can be specified in the extension.add() method as a third argument

 extensions.add("myfunction", myfunction, {
           Php::ByVal("rate", Php::Type::Numeric),
           Php::ByVal("quantity", Php::Type::Numeric)
})

In the above code we have specified that myfunction() will expect two arguments, both of type numeric. The syntax of declaring a ByVal is :

ByVal(const char *name, Php::Type type, bool required = true);

The first argument is the name of the argument, the second defines the type and the third argument defines whether the argument is required or is optional. By default , all arguments are required.

We have a list of predefined Php::Type classes:

Php::Type::Null
Php::Type::Numeric
Php::Type::Float
Php::Type::Bool
Php::Type::Array
Php::Type::Object
Php::Type::String
Php::Type::Resource
Php::Type::Constant
Php::Type::ConstantArray
Php::Type::Callable

Note that Php::ByRef classes are also declared the same way. Using the above example:

 extensions.add("myfunction", myfunction, {
           Php::ByRef("rate", Php::Type::Numeric),
           Php::ByRef("quantity", Php::Type::Numeric)
})

Example Code

Lets add two functions to our helloworld extension. fixedArguments() will take in two numbers and return their sum. fixedArgumentsByRef() will do the same thing but return the sum back in the first argument.

#include <phpcpp.h>
#include <iostream>



 /**
  * Fixed arguments type passed by value
  *
  */
 Php::Value fixedArguments(Php::Parameters &params) {
	
	int arg1 = params[0];
	int arg2 = params[1];

	return (arg1 + arg2);
 }


/**
 * Fixed arguments type passed by ref with one of the args changed in the function
 * 
 */
 void fixedArgumentsByRef(Php::Parameters &params) {
 
	int arg1 = params[0];
	int arg2 = params[1];

	arg1 = arg1 + arg2;
	params[0] = arg1;
 }
/**
 *  tell the compiler that the get_module is a pure C function
 */
extern "C" {
    
    /**
     *  Function that is called by PHP right after the PHP process
     *  has started, and that returns an address of an internal PHP
     *  strucure with all the details and features of your extension
     *
     *  @return void*   a pointer to an address that is understood by PHP
     */
    PHPCPP_EXPORT void *get_module() 
    {
        // static(!) Php::Extension object that should stay in memory
        // for the entire duration of the process (that's why it's static)
        static Php::Extension extension("helloworld", "1.0");
        
        // @todo    add your own functions, classes, namespaces to the extension

		extension.add("fixedArguments", fixedArguments, {
			Php::ByVal("number1", Php::Type::Numeric),
			Php::ByVal("number2", Php::Type::Numeric)
		});

		extension.add("fixedArgumentsByRef", fixedArgumentsByRef, {
			Php::ByRef("number1", Php::Type::Numeric),
			Php::ByRef("number2", Php::Type::Numeric)
		});

        // return the extension
        return extension;
    }
}

Run make and then sudo make install to update the extension

The php test code is given below:

<?php

$total = fixedArguments(1,2);
echo $total . "\n";

$a = 1;
$b = 2;
echo("a=" . $a . ",b=". $b . "\n");
fixedArgumentsByRef($a, $b);
echo("After function: a=" . $a. ",b=". $b . "\n");

?>

 

Both the functions assume that the arguments passed are of the type int. What happens if you pass non-integers as arguments? Eg. fixedArguments(“xxx”, “yyy”). No error or exception will be thrown. Since PHP-CPP will not be able to take the values passed as integers it will use the default values of int for the parameters so it will become 0+0 = 0.

Next: Part 5 Web-enabling your extension

4 Comments

  1. How i can pass an associative array like an object to the function from php file to the extension? then how i will receive it in extension. am doing this:

    myExtension.add(“binary”, binary, {
    Php::ByRef(“number”, Php::Type::Array)
    });

    IS that right?

  2. @mubin. That is correct. You can pass a PHP array using Php::Type::Array and in the C++ code where you implement the function, you handle param[0] as a std:vector. This way you can iterate through the elements. You have to put in type checking , otherwise blindly assuming values to be present will crash the code.

  3. Can you explain the difference between pass by value and pass by reference a little bit more? I have few confusions there.What is the motive of this line in pass by reference function:
    params[0] = arg1;

    • @mubin. When you pass arguments by reference, their values can be changed from inside the called function. When you pass by value, the original values of the arguments cannot be changed from within the function.

2 Trackbacks / Pingbacks

  1. Writing PHP Extensions – Part 3 The Four Kinds of Functions | Truelogic Blog
  2. Writing PHP Extensions – Part 5 Web-enabling your extension | Truelogic Blog

Leave a Reply

Your email address will not be published.


*