This is an old revision of the document!
PHP Native Interface
- Version: 1.0.x
- Date: 2009-03-27
- Author: Paul Biggar paul.biggar@gmail.com
- Status: revising after v1.0
Design of the design of phpni, a native interface for PHP, designed to replace the Zend API.
See also remove_zend_api.
Why do we need a PHP Native Interface?
The rationale is explained separately in remove_zend_api.
//phpni//: The PHP Native Interface
This describes the design of phpni, the PHP Native Interface. This design is in early stages. The stages required until completion are described later.
Design Criteria
- Remove any couping between the Zend Engine, extensions and SAPIs.
- Support all major use cases of the Zend API
- embedding within SAPIs
- proving access to C libraries
- providing the ability to rewrite performance sensitive code in C
Solution
Take the use case of wrapping a C library to expose its functionality in user space. The major idea is to “automatically” import C functions into a special namespace. The PHP library functions would then be comprised of PHP user space code which calls those C functions directly. That way it is possible to craft an API that is separate from the C implementation.
Lets take a simple example. Assume we have a C library XXX, with 3 functions, x, y and z. We'd like to expose this in user space as a class called MyXXX, with methods a and b. We create a file with the signatures of x, y and z:
extensions/xxx/sigs.h
int x (int, int); void y (char*, int); void z (char*, int);
We then write our user space code:
extensions/xxx/MyXXX.php
class MyXXX { function __construct ($username) { $this->username = $username; } function a ($w1, $w2) { $foo = \internals\XXX\x ($w1, $w2); \internals\XXX\y ($this->username, $foo); } function b ($m1, $m2) { $foo = \internals\XXX\x ($m1, $m2); \internals\XXX\z ($this->username, $foo); return $foo; } }
In order to interface between these two, it will be necessary to have a tool to automatically wrap the C functions. SWIG could be used to create this tool.
Zend engine
Since the libraries would no longer use the Zend API, the tight coupling would be broken. It would now be possible to change major parts of the Zend engine without affecting the operation of any other part of PHP.
Extensions/PECL
It would no longer be necessary to know the Zend API to write extensions. Instead, only the API of the C library is necessary, and the interface can be created in PHP user code.
Embed SAPI
The same interface used for libraries can be used to handle many of the use cases of the C API. However, it is likely that a means to call PHP user code from C/C++ code, will be required.
Other PHP implementations
Since PHP extensions are no longer written in the Zend API, other PHP implementations, such as Roadsend, Project Zero, Phalanger and Quercus should be reuse the libraries without difficulty. In addition, if the coupling is between the interpreter and its components is simple enough, it may be possible for other implementations to be slotted in directly. However, though this would be a nice side-effect, it should probably not be considered a priority.
Similar projects
Non-PHP
phpni differs from many of these in that it is designed not to add new features, but instead to replace an existing facility - the ability to call C libraries. As such, dynamic linking is not part of the spec.
- ctypes (Python) http://docs.python.org/library/ctypes.html
- JNA (Java) https://jna.dev.java.net/
- Pyrex (Python) http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
- Cython (Python) http://www.cython.org/
- Haskell 98 Foreign Function Interface http://www.cse.unsw.edu.au/~chak/haskell/ffi/
- CFFI (Common Lisp): Common-Lisp FFI: http://common-lisp.net/project/cffi/
For PHP
There is no reason we shouldn't reuse these, if they fit the bill.
- CodeGen_PECL http://pear.php.net/package/CodeGen_PECL/
- Inline_C http://pear.php.net/package/Inline_C
Project Plan
This is a simple design. In reality, it would need to be prototyped to determine whether this makes sense for every use case, and that there would be little sacrificed to make it work. The work on it should probably progress in roughly the following order:
- Prototype a single library
- perhaps readline?
- Manually write interface code between the header and the PHP code.
- Discuss requirements with other PHP implementations
- Write a utility to generate the interface code automatically
- Using SWIG?
- Test 5 or 6 libraries
- Test more complicated functionality
- Convert entire set of PHP extensions
Naturally, before the last step it will be necessary to get consensus from other internals developers that this is a good idea. It would be worthwhile to produce a document discussing the experience so far.