3 [![Join the chat at https://gitter.im/m6w6/ext-psi](https://badges.gitter.im/m6w6/ext-psi.svg)](https://gitter.im/m6w6/ext-psi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 [![Build Status](https://travis-ci.org/m6w6/ext-psi.svg?branch=master)](https://travis-ci.org/m6w6/ext-psi)
6 PSI is a PHP extension, which provides a foreign function interface through
7 `libffi` and/or `libjit`.
9 The acronym PSI may be read as:
10 * PHP System Interface
17 * structs, unions, enums and typedefs
18 * numeric and boolean expressions
25 > This is heavy WIP. Installation only works from a source checkout
26 > with php-src@master on x86_64-linux yet.
27 > Sort of works on x64_64-darwin, too, roughly.
31 > Not implemented yet.
33 This extension is distributed through [PECL](http://pecl.php.net) and can be
34 installed with [PEAR](http://pear.php.net)'s pecl command:
40 > Not implemented yet.
42 Watch out for [PECL replicates](https://replicator.pharext.org?psi)
43 and [pharext](https://github.com/pharext) packages attached to
44 [releases](https://github.com/m6w6/ext-psi/releases).
48 This extension is hosted at [Github](https://github.com/m6w6/ext-psi) with a
49 personal [mirror](https://git.m6w6.name/?p=m6w6/ext-psi) available.
51 git clone github.com:m6w6/ext-psi
56 ./configure --with-php-config=/path/to/php-config
60 ## Configuring PSI at build time
62 PSI supports the following configure switches:
65 **Enable PHP System Interface support.**
67 This is only relevant for an in-tree build. Use `--enable-psi` to include
68 the PSI extension in the build.
74 > We currently rely on a patched libjit, because of an apparent bug in how
75 > libjit creates closures, which still needs to be verified, though.
76 > See https://github.com/m6w6/libjit for the preliminary patch.
81 ## Configuring PSI at runtime
85 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
89 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
91 ### psi.blacklist.decls
93 A comma separated list of C function declarations to ignore.
95 ### psi.blacklist.vars
97 A comma separated list of C variable declarations to ignore.
101 PSI files are augmented C header files. So, everything usually found in C
102 headers including comments, preprocessor directives, typedefs, structs,
103 unions, enums, function and variable declarations should work.
105 That means, that you can just include C headers in the usual way:
111 ### Dynamic Libraries
113 PSI needs to know which library it should `dlopen` unless the declared functions
114 are provided by the standard C library. Therefore the PSI preprocessor
115 understands a special pragma:
124 const int num\ZERO = 0;
125 const string pwd\TOKEN = "4WlOjXGL";
128 Constants must have namespaced identifiers and are registered as userland constants.
130 C enums and preprocessor macros with numerical or string expressions are
131 automatically discovered and registered as constants.
135 Implementations are the userland visible interfaces to the foreign function interface.
138 function str\error(int $num) : string {
139 let errnum = intval($num);
140 return strerror(errnum) as to_string(strerror);
144 Each implementation refers to exactly one declared foreign function referenced in its `return` statement. Each native function, on the other hand, may have any number of implementations.
150 /* needed for setkey() in stdlib.h */
160 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
161 // there must be a `let` statement for each
162 // declared argument of the called function
164 // setup a pointer to NULL
167 // setup a string pointer to $host
168 let host = strval($host);
170 // assing the integer value of $flags
171 let flags = intval($flags);
173 // the function to call is referenced in
174 // the return statement, along with the
175 // necessary cast how to interpret the
176 // returned native value
177 return idna_to_ascii_8z(host, buffer, flags)
178 as to_int(idna_to_ascii_8z);
180 // by-ref vars might receive output values
181 // through `set` statments, which also
182 // require a cast how to marshal the
183 // native data as PHP value
184 set $result = to_string(*buffer);
186 // after the buffer has been marshaled
187 // for the PHP engine, we have to free
188 // the buffer to avoid a memory leak
190 // note that in this example we omit the
191 // declaration of the free() function called
192 // in our `free` statement for brevity
195 function idn\strerror(int $rc) : string {
196 return to_string(idna_strerror);
197 let rc = intval($rc);
204 $rc = idn\utf8_to_ascii("flöte.de", $result);
205 printf("<%s>\n", $result);
206 printf("%s\n", idn\strerror($rc));
208 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
209 printf("<%s>\n", $result);
210 printf("%s\n", idn\strerror($rc));
218 Non-digit/letter/hyphen in input
223 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
224 the accompanying [LICENSE](./LICENSE) file.
228 All forms of contribution are welcome! Please see the bundled
229 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
231 The list of past and current contributors is maintained in [THANKS](./THANKS).