Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Php extensions

602 views

Published on

Writing Extensions for PHP 7

Published in: Internet
  • Be the first to comment

Php extensions

  1. 1. PHP EXTENSIONS Making the language even better
  2. 2. 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
  3. 3. WARNING! The things shown here to apply to PHP 7 only!
  4. 4. 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
  5. 5. But I want to change the engine! Baby steps, baby steps
  6. 6. Wrapper Extension Speed and/or Algorithm Extension Zend Extension SAPI Engine - Lexer, AST, Parser
  7. 7. 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 https://php-lxr.adamharvey.name/source/
  8. 8. But I want to learn C
  9. 9. Also try: • http://www.learn-c.org/ • http://c.learncodethehardway.org/book/ • http://aelinik.free.fr/c/ Practice Practice Practice!
  10. 10. Preparing to Compile The big list
  11. 11. Quick Setup Needs 1. compiler 2. sdk 3. tools 4. dependencies 5. code phpize is your friend!
  12. 12. How to Compile an Extension 1. phpize 2. ./configure 3. make 4. make install 5. make test configure might require –with-php-config=/path/to/something but…
  13. 13. But wait – there’s more! • Compile your own PHP source, use a –prefix  /usr/local/php-7.0-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 gcc and do things like use static analysis
  14. 14. 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. makephp 7
  15. 15. How to Play along git clone https://github.com/auroraeosrose/php-extensions- code.git git clone git://github.com/auroraeosrose/php- extensions-code.git git checkout scaffolding phpize ./configure make make test
  16. 16. Let’s write an extension! But wait – there’s more….
  17. 17. 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
  18. 18. DOIN IT RONG
  19. 19. Which do YOU want?
  20. 20. 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?
  21. 21. 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…
  22. 22. FFI
  23. 23. 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 • There’s MFFI but it’s not done  https://github.com/mgdm/MFFI • Are you interested and not afraid? See me!
  24. 24. 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
  25. 25. Google says…
  26. 26. 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/
  27. 27. 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
  28. 28. 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
  29. 29. Configure files
  30. 30. Module struct
  31. 31. 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!
  32. 32. 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
  33. 33. 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
  34. 34. PHPT tests
  35. 35. Let’s take a break here for some semi-live demos…
  36. 36. Zval The guts behind PHP’s type system
  37. 37. 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
  38. 38. zval
  39. 39. zval continued…
  40. 40. For more on the new zval https://nikic.github.io/2015/05/05/Internal-value-representation-in- PHP-7-part-1.html
  41. 41. long any numeric double numeric with decimal char* + size_t (length) strings, binary Hashtable dictionaries, arrays,structs object any complicated type
  42. 42. For more on the new string type http://jpauli.github.io/2015/09/18/php-string-management.html
  43. 43. 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_OBJ(zval) Z_OBJ_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)
  44. 44. My extension does nothing! Back to our regularly schedule content
  45. 45. 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
  46. 46. 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)
  47. 47. Anatomy of a Function
  48. 48. 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 
  49. 49. php type code 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 zend_long integer L zend_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*, size_t resource r zval * string (possible null bytes) s char*, size_t actual zval z zval * actual zval Z zval**
  50. 50. zend_parse_parameters type 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
  51. 51. return_value RETURN_RES(l) RETURN_BOOL(b) RETURN_NULL() RETURN_LONG(l) RETURN_DOUBLE(d) RETURN_STRING(s) RETURN_STRINGL(s, l) RETURN_EMPTY_STRING() RETURN_ZVAL(zv, copy, dtor) RETURN_FALSE RETURN_TRUE RETVAL_RES(l) RETVAL_BOOL(b) RETVAL_NULL() RETVAL_LONG(l) RETVAL_DOUBLE(d) RETVAL_STRING(s) RETVAL_STRINGL(s, l) RETVAL_EMPTY_STRING() RETVAL_ZVAL(zv, copy, dtor) RETVAL_FALSE RETVAL_TRUE
  52. 52. 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()
  53. 53. Now to visit the attach-library branch…
  54. 54. 1. namespaces 2. classes 3. methods 4. constants Step 9. Make it shiny
  55. 55. 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)
  56. 56. add-basic-class branch
  57. 57. Lifecycle Let’s take a moment to learn about how PHP works internally
  58. 58. 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
  59. 59. 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
  60. 60. Class Properties
  61. 61. add-class-properties branch
  62. 62. Class Constants
  63. 63. add-class-constants branch
  64. 64. My class does nothing! Methods are where it’s at
  65. 65. Class Methods
  66. 66. add-class-methods branch
  67. 67. Alter $this
  68. 68. manipulate this branch
  69. 69. Abstract, Interface, Trait Class 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)
  70. 70. 1. globals 2. memory management 3. custom objects 4. object handlers 5. thread safety Step 10: Advanced topics
  71. 71. 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)
  72. 72. 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
  73. 73. 1. clean up what you emalloc (C level destructor) 2. read wiki on how to make them extendable!
  74. 74. 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 pecl-dev@lists.php.net 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
  75. 75. 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 6. Complex objects with handlers
  76. 76. About Me  http://emsmith.net  auroraeosrose@gmail.com  twitter - @auroraeosrose  IRC – freenode – auroraeosrose  #phpmentoring  #gophp7-ext  https://joind.in/talk/56f05
  77. 77. Questions? HELP WITH DOCS! http://edit.php.net http://wiki.php.net/internals HELP WITH THE FUTURE http://gophp7.org/gophp7-ext

×