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.
30 This extension is distributed through [PECL](http://pecl.php.net) and can be
31 installed with [PEAR](http://pear.php.net)'s pecl command:
37 Watch out for [PECL replicates](https://replicator.pharext.org?psi)
38 and [pharext](https://github.com/pharext) packages attached to
39 [releases](https://github.com/m6w6/ext-psi/releases).
43 This extension is hosted at [Github](https://github.com/m6w6/ext-psi) with a
44 personal [mirror](https://git.m6w6.name/?p=m6w6/ext-psi) available.
46 git clone github.com:m6w6/ext-psi
51 ./configure --with-php-config=/path/to/php-config
55 ## Configuring PSI at build time
57 PSI supports the following configure switches:
60 **Enable PHP System Interface support.**
62 This is only relevant for an in-tree build. Use `--enable-psi` to include
63 the PSI extension in the build.
69 > We currently rely on a patched libjit, because of an apparent bug in how
70 > libjit creates closures, which still needs to be verified, though.
71 > See https://github.com/m6w6/libjit for the preliminary patch.
76 ## Configuring PSI at runtime
80 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
84 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
86 ### psi.blacklist.decls
88 A comma separated list of C function declarations to ignore.
90 ### psi.blacklist.vars
92 A comma separated list of C variable declarations to ignore.
107 * C style multi line comments
108 * C++ style single line comments
111 // this is a one line comment
121 typedef unsigned char xmlChar;
124 They follow the basic C-style `typedef` syntax.
132 You can also `typedef` unions and enums that way.
136 The following example results in exactly the same interpretation as the previous:
139 typedef struct str str_t;
146 A struct will have the size of all its elements plus padding combined and an
147 alignment equal to that of the largest element's alignment.
151 Enums are considered to be of type `int`.
160 Enums will be registered as userland constants with the following pattern:
162 * `psi\STATUS\FAILURE` with value -1
163 * `psi\STATUS\SUCCESS` with value 0
179 Unions will have the size and alignment of the largest element they contain.
187 These statements define what library should be `dlopen()`-ed to look up symbols from declarations.
188 When a `lib` statement is omitted, stdlib is assumed.
192 Declarations provide all information needed to make a foreign function call.
195 extern char *strerror(int errnum);
198 You may specify a non-standard calling convention in place of `extern`, where `default` and `cdecl` have the same meaning as `extern`.
200 Additionally recognized calling conventions include: `stdcall` and `fastcall`.
205 const int num\ZERO = 0;
206 const string pwd\TOKEN = "4WlOjXGL";
209 Constants must have a namespaced identifiers and are registered as userland constants.
213 Implementations are the userland visible interfaces to the foreign function interface.
216 function str\error(int $num) : string {
217 let errnum = intval($num);
218 return to_string(strerror);
222 Each implementation refers to exactly one declared foreign function referenced in its `return` statement. Each declaration, on the other hand, may have any number of implementations.
227 // all declarations in this file should be looked up in libidn
231 const int \IDNA_SUCCESS = 0;
232 const int \IDNA_STRINGPREP_ERROR = 1;
233 const int \IDNA_PUNYCODE_ERROR = 2;
234 const int \IDNA_CONTAINS_NON_LDH = 3;
235 const int \IDNA_CONTAINS_LDH = 3;
236 const int \IDNA_CONTAINS_MINUS = 4;
237 const int \IDNA_INVALID_LENGTH = 5;
238 const int \IDNA_NO_ACE_PREFIX = 6;
239 const int \IDNA_ROUNDTRIP_VERIFY_ERROR = 7;
240 const int \IDNA_CONTAINS_ACE_PREFIX = 8;
241 const int \IDNA_ICONV_ERROR = 9;
242 const int \IDNA_MALLOC_ERROR = 201;
243 const int \IDNA_DLOPEN_ERROR = 202;
245 const int \IDNA_ALLOW_UNASSIGNED = 1;
246 const int \IDNA_USE_STD3_ASCII_RULES = 2;
248 // nothing special about the declaration here
249 default int idna_to_ascii_8z(char *host, char **buffer, int flags);
251 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
252 // there must be a `let` statement for each
253 // declared argument of the called function
255 // setup a pointer to NULL
258 // setup a string pointer to $host
259 let host = strval($host);
261 // assing the integer value of $flags
262 let flags = intval($flags);
264 // the function to call is referenced in
265 // the return statement, along with the
266 // neccessary cast how to interpred the
267 // returned native value
268 return to_int(idna_to_ascii_8z);
270 // by-ref vars might receive output values
271 // through `set` statments, which also
272 // require a cast how to marshal the
273 // native data as PHP value
274 set $result = to_string(*buffer);
276 // after the buffer has been marshaled
277 // for the PHP engine, we have to free
278 // the buffer to avoid a memory leak
280 // note that in this example we omit the
281 // declaration of the free() function called
282 // in our `free` statement for brevity
285 default char *idna_strerror(int rc);
286 function idn\strerror(int $rc) : string {
287 return to_string(idna_strerror);
288 let rc = intval($rc);
295 $rc = idn\utf8_to_ascii("flöte.de", $result);
296 printf("<%s>\n", $result);
297 printf("%s\n", idn\strerror($rc));
299 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
300 printf("<%s>\n", $result);
301 printf("%s\n", idn\strerror($rc));
309 Non-digit/letter/hyphen in input
314 A comprehensive list of changes can be obtained from the
315 [PECL website](https://pecl.php.net/package-changelog.php?package=psi).
317 Known issues are listed in [BUGS](./BUGS) and future ideas can be found in [TODO](./TODO).
321 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
322 the accompanying [LICENSE](./LICENSE) file.
326 All forms of contribution are welcome! Please see the bundled
327 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
329 The list of past and current contributors is maintained in [THANKS](./THANKS).