Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Building Custom PHP Extensions
1. Building Custom PHP
Extensions
International PHP Conference 2012 Tbilisi, Georgia
Wednesday, December 12, 12
2. About me
‣ Ioseb Dzmanashvili
‣ Software Architect at AzRy LLC
‣ Teacher at Caucasus School of Technology
‣ V8 JavaScript engine contributor
‣ Author of uri_template PHP extension
‣ Author of Create-Form and Edit-Form link relation
types (being RFCed now).
Wednesday, December 12, 12
3. This talk covers
‣ Setting up development environment
‣ Creating extension skeletons with automated tools
‣ Building and installing extensions
‣ Internals such as:
‣ Implementing and exposing C functions
‣ PHP parameter parsing
‣ Variables
Wednesday, December 12, 12
5. My Experience
‣ URI Template Pecl extension
‣ https://github.com/ioseb/uri-template
‣ Available from Pecl channel
‣ http://pecl.php.net/package/uri_template
‣ Used by Guzzle HTTP client library and Drupal 8
Wednesday, December 12, 12
6. What it does?
‣ Implementation of RFC6570(URI Template)
‣ Resource Identifier - URI)
100% compatibility with RFC3986 (Uniform
‣ 100% compatibility with RFC3629 (UTF-8)
Wednesday, December 12, 12
7. How to use it?
// URI Template Data
$data = array(
"id" => array("person","albums"),
"token" => "12345",
"fields" => array("id", "name", "picture"),
);
// URI Template
$template = "{/id*}{?fields,token}";
// Transformation
$result = uri_template($template, $data);
//Produces:
/person/albums?fields=id,name,picture&token=12345
Wednesday, December 12, 12
8. Why it is important?
‣ Possibility to achieve outstanding performance
‣ Possibility to learn PHP from inside out
Wednesday, December 12, 12
10. Installing PHP dev package
‣ Linux(Debian)
$ sudo apt-get install php5-dev
‣ Installing with Mac Ports on Mac OS X
$ sudo port install php5-devel
‣ Use XAMPP developer package as an alternative
for Mac OS X (painless solution)
Wednesday, December 12, 12
11. Creating extension
‣ Creating the configuration and build files
‣ Creating the header and basic C files, which includes:
‣ Creating initialization and destruction functions
‣ Including the correct headers
‣ Creating functions for use by PHP info tools
‣ Creating test files
Wednesday, December 12, 12
12. Tools for creating extensions
‣ Create extension manually
‣ Use ext_skel to generate extension
‣ Use pecl-gen to generate extension
Wednesday, December 12, 12
13. Generating extension
with pecl-gen
‣ Install codegen_pecl
$ pear install codegen_pecl
‣ Create XML descriptor for extension
‣ Generate extension skeleton
$ pecl-gen hello-world.xml
Wednesday, December 12, 12
14. XML descriptor (hello-world.xml)
<?xml version="1.0" ?>
<extension name="hello_world" version="0.1.0">
<summary>Yet another hello world PHP Extension</summary>
<description>
This is a sample "hello world" extension
for demonstration purposes only.
</description>
<maintainers>
<maintainer>
<user>ioseb</user>
<name>Ioseb Dzmanashvili</name>
<email>ioseb.dzmanashvili@gmail.com</email>
<role>lead</role>
</maintainer>
</maintainers>
<license>PHP</license>
<function name="hello_world" role="public">
<proto>void hello_world( string input )</proto>
<summary>Prints a hello world message</summary>
<code><![CDATA[ // C code goes here ]]></code>
</function>
</extension>
Wednesday, December 12, 12
16. Generated hello_world() function
PHP_FUNCTION(hello_world)
{
const char * input = NULL;
int input_len = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s", &input, &input_len) == FAILURE) {
return;
}
do {
// C code goes here
} while (0);
}
Wednesday, December 12, 12
17. Modifying hello_world() function
PHP_FUNCTION(hello_world)
{
const char * input = NULL;
int input_len = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s", &input, &input_len) == FAILURE) {
return;
}
// our implementation
php_printf("Hello world %s", input);
}
Wednesday, December 12, 12
18. Installing extension
‣ Prepare build environment for PHP extension
$ phpize
‣ Configure it
$ ./configure
‣ Compile & Install
$ make && sudo make install
‣ Enable extension
$ php -d extension=hello_world.so -m
Wednesday, December 12, 12
19. Testing hello_world() function
‣ Create test.php file
‣ Write test code
<?php
echo hello_world("PHP Rocks");
echo "n";
‣ Run script
$ php test.php
‣ If you see following line everything is OK
$ Hello world PHP Rocks
Wednesday, December 12, 12
20. Cleaning extension folder
‣ Get rid off compilation output
$ make clean
‣ Get rid off build environment stuff
$ phpize --clean
Wednesday, December 12, 12
22. PHP_FUNCTION expansion
PHP_FUNCTION(hello_world)
{
// rest of code removed for brevity
}
expands to
void zif_hello_world(
zval *return_value, // 1) variable to store return value
char return_value_used, // 2) if returned value was used
zval *this_ptr TSRMLS_DC // 3) pointer to object's internal state
)
Wednesday, December 12, 12
24. Parsing Function Parameters
PHP_FUNCTION(hello_world)
{
const char *input = NULL; // variable to store parameter value
int input_len = 0; // variable to store value length
if (zend_parse_parameters(
ZEND_NUM_ARGS() TSRMLS_CC, // 1) number of arguments
"s", // 2) format string
&input, // 3) address of *input variable
&input_len // 4) address of input_len variable
) == FAILURE) {
return; // just return if something goes wrong
}
// actual implementation
php_printf("Hello world %s", input);
}
Wednesday, December 12, 12
25. Available Parameter Types
Type Specifier C datatype PHP Type
b zend_bool Boolean
l long Integer
d double Floating point
s char*, int String
r zval* Resource
a zval* Array
o zval* Object instance
O zval*, zend_class_entry* Object of a specified type
z zval* Non-specific zval
Z zval** Dereferenced zval
Wednesday, December 12, 12
26. Examples of parameter formats
// means that function expects:
// a) required long parameter
// b) required string parameter
// c) optional long parameter
// d) optional zval of non-specific type
zend_parse_parameters(..., "ls|lz", ...)
// menas that function expects:
// a) required array parameter
// b) required array parameter
// c) required string parameter
// d) optional long parameter
zend_parse_parameters(..., "aas|l", ...)
Wednesday, December 12, 12
27. Zval
_zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
typedef struct _zval_struct zval;
Wednesday, December 12, 12
28. Zval - Graphical Representation
value
long lval
double dval
str char *val int len
HashTable *ht
zend_object_value obj
refcount__gc
type
is_ref__gc
Wednesday, December 12, 12
29. Internal Data Types
Type Value Access Macros
IS_NULL N/A
IS_BOOL Z_BVAL_P(value)
IS_LONG Z_LVAL_P(value)
IS_DOUBLE Z_DVAL_P(value)
IS_STRING Z_STRVAL_P(value), Z_STRLEN_P(value)
IS_ARRAY Z_ARRVAL_P(value)
IS_OBJECT Z_OBJVAL_P(value)
IS_RESOURCE Z_RESVAL_P(value)
Wednesday, December 12, 12
30. Zval Reader Example
void display_zval(zval *value)
{
switch(Z_TYPE_P(value)) {
case IS_NULL:
php_printf("NULL"); break;
case IS_BOOL:
php_printf("BOOL %d", Z_BVAL_P(value) ? 1 : 0); break;
case IS_LONG:
php_printf("LONG %ld", Z_LVAL_P(value)); break;
case IS_DOUBLE:
php_printf("DOUBLE %f", Z_DVAL_P(value)); break;
case IS_STRING:
php_printf("STRING %s", Z_STRVAL_P(value)); break;
case IS_RESOURCE:
php_printf("RES #%ld", Z_RESVAL_P(value)); break;
case IS_ARRAY:
php_printf("ARRAY"); break;
case IS_OBJECT:
php_printf("OBJECT"); break;
}
}
Wednesday, December 12, 12