php extensions

81
PHP EXTENSIONS Making the language even better

Upload: elizabeth-smith

Post on 16-Jul-2015

527 views

Category:

Internet


0 download

TRANSCRIPT

PHP EXTENSIONSMaking the language even better

Congratulations!• You’ve decided to learn “down the stack”

• You’ll learn more than you do “across the stack”

• Your brain will hurt a bit

• This will require you to be involved in your own learning process

• It is HARD WORK to be good at anything new

WARNING!The things shown here to apply to PHP 5.4 – PHP 5.x

Why do extensions?• Talk to a C or C++ library

• Modify the way the engine works (zend extensions usually)

• Make slow parts of code run faster

But I want to change the engine!Baby steps, baby steps

Wrapper Extension

Speed and/or Algorithm Extension

ZendExtension

SAPI

Engine - Lexer, AST, Parser

But I don’t know C!1. compiled

2. strictly typed

3. php internals do “hard” stuff

4. copy and paste! boilerplate and macros

5. cairo, pecl_http, date

6. Don’t do the hard stuff first!

lxr.php.net

But I want to learn C

Also try:• http://www.learn-c.org/

• http://c.learncodethehardway.org/book/

• http://aelinik.free.fr/c/

Practice Practice Practice!

Preparing to CompileThe big list

Quick Setup Needs1. compiler

2. sdk

3. tools

4. dependencies

5. code

phpize is your friend!

How to Compile an Extension1. phpize

2. ./configure

3. make

4. make install

5. make test

configure might require –with-php-config=/path/to/something

but…

But wait – there’s more!• Compile your own PHP source, use a –prefix

/usr/local/php-5.6-debug-zts is one I use

I also have 20 php’s installed

• We want developer specific flags

--enable-maintainer-zts and --enable-debug

optionally –enable-gcov

• install gdb and valgrind and optionally lcov

• this is easy on Ubuntu and similar systems where packages are easy to get

• You can also compile php with clang instead of gccand do things like use static analysis

Rasmus to the Rescue!• https://github.com/rlerdorf/php7dev/blob/master/README.md

tl;dr

1. install virtualbox

2. install vagrant

3. git clone https://github.com/rlerdorf/php7dev.git

4. cd php7dev

5. vagrant up

6. vagrant ssh

7. sudo newphp 56 debug zts

How to Play alonggit clone https://github.com/auroraeosrose/php-extensions-code.git

git clone git://github.com/auroraeosrose/php-extensions-code.git

git checkout scaffolding

bookmark lxr.php.net – you will be using it a lot

phpize

./configure

make

make test

Let’s write an extension!But wait – there’s more….

1. Set up compile environment

2. Write a module definition

3. Learn about the PHP lifecycle

4. Learn about zvals

5. Add functions

6. ???

7. Profit!

Every Other Extensions Talk

DOIN IT RONG

Which do YOU want?

1. Do something you can’t do in userland

2. Utilize a C library

3. Make slow code faster

Maybe you should just use ffi!

Step 1. Why?

What is FFI?• Foreign function interface

• Java calls it JNI

• HHVM calls it HNI

• Python calls it “ctypes” (do not ask, stupidest name ever)

• C# calls it P/Invoke

• Ruby calls it FFI

• PHP calls it…

FFI

Oh wait…• php’s ffi is rather broken (last release is 2004-01-20)

• php’s ffi has no maintainer (ilia and wez were doing it)

• It needs some TLC

• Are you interested and not afraid? See me!

1. I hate parsing URIs

2. PHP’s parse_url is… not the best

3. How about an extension that wraps something

that parses uris in an excellent fashion

4. RESEARCH TIME

Step 2. What

Google says…

C library to the rescue!• uriparser.sourceforge.net

• strictly RFC 3986 compliant

• available on many systems as packages

• cross platform

• documented http://uriparser.sourceforge.net/doc/html/

1. Think about what the API should be

2. Look at the C APIs but don’t mimic them

3. Write an example of how you WANT it to work

4. Write more then one example!

5. Turn these examples into your first tests

6. Yes this is TDD

Step 3. How

1. This is copy and paste

1. config.m4 & config.w32

2. macros for version api changes if necessary

3. main module file (php_{$ext}.c)

4. main header file (php_{$ext}.h)

2. Compile it and test!

Step 6. Extension Scaffolding

Configure files

Module struct

Scaffolding rules

1. make sure you name your files in a standard way

2. document! use a license header, proto statements

3. read the coding standards

http://lxr.php.net/xref/PHP_5_6/CODING_STANDA

RDS

4. FOLLOW THE CODING STANDARDS

5. use version control early on – github is easy!

php –d extension=myext.so –m

The scaffold extension should show up in the list

Make sure to

1. define a version constant

2. read and use PHP code standards

Check if it works

1. run-test.php

2. make test will magically have output

more at http://qa.php.net/write-test.php and docs

at http://qa.php.net/phpt_details.php

Step 7. Write the test

PHPT tests

Let’s take a break here for some semi-live demos…

ZvalThe guts behind PHP’s type system

Typing systems compared

Static Typing (C)

• Variables must be declared before use

• Variables must be given a type at declaration

• “compile time” checking

Dynamic Typing (PHP)

• Variables don’t have to be declared before use

• Variables can change types

• “run time” checking

zval

long any numeric

double numeric with decimal

char* + int(length) strings, binary

Hashtable dictionaries, arrays,structs

object any complicated type

How do I get C types from a ZVAL?

Z_LVAL(zval) Z_LVAL_P(zval_p) Z_LVAL_PP(zval_pp)

Z_BVAL(zval) Z_BVAL_P(zval_p) Z_BVAL_PP(zval_pp)

Z_DVAL(zval) Z_DVAL_P(zval_p) Z_DVAL_PP(zval_pp)

Z_STRVAL(zval) Z_STRVAL_P(zval_p) Z_STRVAL_PP(zval_pp)

Z_STRLEN(zval) Z_STRLEN_P(zval_p) Z_STRLEN_PP(zval_pp)

Z_ARRVAL(zval) Z_ARRVAL_P(zval_p) Z_ARRVAL_PP(zval_pp)

Z_OBJVAL(zval) Z_OBJVAL_P(zval_p) Z_OBJVAL_PP(zval_pp)

Z_OBJ_HANDLE(zv

al)

Z_OBJ_HANDLE_P(zval

_p)

Z_OBJ_HANDLE_PP(zval_

pp)

Z_OBJ_HT(zval) Z_OBJ_HT_P(zval_p) Z_OBJ_HT_PP(zval_pp)

Z_OBJCE(zval) Z_OBJCE_P(zval_p) Z_OBJCE_PP(zval_pp)

Z_OBJPROP(zval) Z_OBJPROP_P(zval_p) Z_OBJPROP_PP(zval_pp)

Z_TYPE(zval) Z_TYPE_P(zval_p) Z_TYPE_PP(zval_pp)

My extension does nothing!Back to our regularly schedule content

1. tell it to link to our C library

2. add a function

3. learn how to get data

4. learn how to return data

Step 8. Actually do something

I hate autotools…• Also known as the gnu build system

• provider of much pain, but much good use as well

• autoconf – generates a configure script (we cheat with phpize on shared extensions) makes a configure we run to set up our information,

mainly a config.h file

• automake – creates makefiles

• libtool – creates static and dynamic libraries

• Windows? Well php wrote it’s own version of autotools – in jscript (windows javascript variant)

Anatomy of a Function

Wait – what was that?• Define your function in C

use a special call to parse parameters passed by the user

use a special zval to return data to the user

• Tell PHP your extension provides this function

put it in your “giant struct of doom” that lists them all

send it to php when in your module struct

• Tell PHP what arguments your extension provides

If your argument information and zpp argue users will be angry

Yes it sucks you can’t just do one

php typecode

c type

array or object a zval *

boolean b zend_bool

class C zend_class_entry *

double d double

callable f zend_fcall_info andzend_fcall_info_cache

array or HASH_OF(object) H HashTable*

array h HashTable*

integer l long (NOT INT)

integer L long with LONG_MAX, LONG_MIN limits

object o zval *

object of specific type O zval *, zend_class_entry

string (no null bytes) p char*, int

resource r zval *

string (possible null bytes) s char*, int

actual zval z zval *

actual zval Z zval**

zend_parse_parameterstype

code

variable args (any) * int, zval***

variable args (1 or more) + int, zval***

| anything after is optional, use defaults

/ use SEPARATE_ZVAL_IF_NOT_REF

doesn’t apply to b, l, and d ! C NULL for zval null

return_valueRETURN_RESOURCE(l)

RETURN_BOOL(b)

RETURN_NULL()

RETURN_LONG(l)

RETURN_DOUBLE(d)

RETURN_STRING(s, duplicate)

RETURN_STRINGL(s, l, duplicate)

RETURN_EMPTY_STRING()

RETURN_ZVAL(zv, copy, dtor)

RETURN_FALSE

RETURN_TRUE

RETVAL_RESOURCE(l)

RETVAL_BOOL(b)

RETVAL_NULL()

RETVAL_LONG(l)

RETVAL_DOUBLE(d)

RETVAL_STRING(s, duplicate)

RETVAL_STRINGL(s, l, duplicate)

RETVAL_EMPTY_STRING()

RETVAL_ZVAL(zv, copy, dtor)

RETVAL_FALSE

RETVAL_TRUE

Complex Data

array_init()

add_(index|assoc)_long()

add_(index|assoc)_bool()

add_(index|assoc)_string()

object_init()

add_property_long()

add_property_bool()

add_property_string()

Now to visit the attach-library branch…

1. namespaces

2. classes

3. methods

4. constants

Step 9. Make it shiny

Classes

1. name, parent, and flags

2. hashtables of methods, default methods, static

methods

3. hashtables of static properties, default

properties, and properties

4. object handlers

5. union of either file information, or internal

structures (for internal classes)

add-basic-class branch

LifecycleLet’s take a moment to learn about how PHP works internally

Lifecycle

PHP stops

MSHUTDOWN – for each extension

RSHUTDOWN – for each request

cleanup after test.php

RINIT – for each request

execute test.php

MINIT – for each extension

request/parse test.php

PHP starts

php test.php

Lifecycle Threaded

PHP stops

MSHUTDOWN – for each extension

request index.php request foo.php

RINIT – for each request

• execute test.php

RSHUTDOWN – for each request

• cleanup after test.php

RINIT – for each request

• execute test.php

RSHUTDOWN – for each request

• cleanup after test.php

MINIT – for each extension

apache starts

Class Properties

add-class-properties branch

Class Constants

add-class-constants branch

My class does nothing!Methods are where it’s at

Class Methods

add-class-methods branch

Alter $this

manipulate this branch

Abstract, Interface, TraitClass Method

ZEND_ACC_IMPLICIT_ABSTRACT_CLA

SS

ZEND_ACC_STATIC

ZEND_ACC_EXPLICIT_ABSTRACT_CLA

SS

ZEND_ACC_ABSTRACT

ZEND_ACC_FINAL_CLASS ZEND_ACC_FINAL

ZEND_ACC_INTERFACE ZEND_ACC_PUBLIC

ZEND_ACC_TRAIT ZEND_ACC_PROTECTED

ZEND_ACC_PRIVATE

ZEND_ACC_CTOR

ZEND_ACC_DTOR

ZEND_ACC_CLONE spl_ce_FilterIterator->ce_flags |=

ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;

PHP_ME(DateTime, __construct, arginfo_date_create,

ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)

1. globals

2. memory management

3. custom objects

4. object handlers

5. thread safety

Step 10: Advanced topics

1. in your header – use

ZEND_BEGIN|END_MODULE_GLOBALS

2. create the global access macro in your header

(copy and paste)

3. ZEND_DECLARE_MODULE_GLOBALS in

every file where you will use them

4. use the macro to access

COUNTER_G(basic_counter_value)); }

5. Create ginit/gshutdown functions if your globals

need initializing , etc

Global Variables (threads = evil)

emalloc( )

• allocates the specified number of bytes

safe_emalloc()

• like emalloc but adds a special protection against overflows

efree( )

• releases the specified block of memory back to the system

estrdup( )

• allocate a buffer and copy the string into that buffer

estrndup( )

• same as estrdup when you already know the length of the string

ecalloc( )

• allocates the number of bytes and initializes them to zero

erealloc( )

• resizes the specified block of memory

https://wiki.php.net/internals/zend_mm

1. clean up what you emalloc (C level destructor)

2. read wiki on how to make them extendable!

Object Handlers (black magic)

https://wiki.php.net/internals/engine/objects

TSRM

thread safe resource manager

ZTS

zend thread safety

• tsrm_lsTSRMLS_C

• void ***tsrm_lsTSRMLS_D

• , tsrm_lsTSRMLS_CC

• , void ***tsrm_lsTSRMLS_DC

1. http://edit.php.net

2. http://svn.php.net/viewvc/phpdoc/en/trunk/reference/

3. PhD is awesomesauce

• http://doc.php.net/phd/

4. email [email protected]

1. who you are

2. what you wrote (with links to your code!)

3. why you think it should be in pecl

5. poke me (or other devs)

Document, PECL, release

Stuff I didn’t talk about

1. resources (use custom objects instead)

2. ini entries (just DON’T)

3. threading and parallel processing

4. engine hooking

5. streams and transports

PHP 7 is coming!gophp7-ext and php extension ecosystems

About Me

http://emsmith.net

[email protected]

twitter - @auroraeosrose

IRC – freenode – auroraeosrose

#phpmentoring

#gophp7-ext

Questions?

HELP WITH DOCS!

http://edit.php.net

http://wiki.php.net/internals

HELP WITH THE FUTURE

http://gophp7.org/gophp7-ext