PHP to Zig function conversion ᴾᴴᴾ - chung-leong/zigar GitHub Wiki
JavaScript | PHP
The constructor of a Zig function type can be used to convert a PHP function into a Zig one:
const std = @import("std");
pub const Callback = fn (i32, []const u8) void;
pub fn setCallback(_: ?*const Callback) void {}
<?php
$m = zigar_use(__DIR__ . '/php-fn-example-1.zig');
function hello($number, $text) {
echo "number = $number, text = $text\n";
};
$callback = new $m->Callback('hello');
print_r($callback);
fn (i32, []const u8) void Object
(
)
The constructor creates a Zig-to-PHP bridge, a small dynamically generated Zig function that invokes the given PHP function.
In the example above, we can pass callback to setCallback(). It wouldn't do anything,
of course, as it's not implemented yet. Let us do that now:
const std = @import("std");
const zigar = @import("zigar");
pub const Callback = fn (i32, []const u8) void;
pub fn none(_: i32, _: []const u8) void {}
var callback: *const Callback = &none;
pub fn setCallback(cb: ?*const Callback) void {
zigar.function.release(callback);
callback = cb orelse &none;
}
pub fn runCallback() void {
callback(123, "Hello world");
}
<?php
$m = zigar_use(__DIR__ . '/php-fn-example-2.zig');
function hello($number, $text) {
echo "number = $number, text = $text\n";
}
$callback = new $m->Callback('hello');
$m->setCallback($callback);
$m->runCallback();
$m->setCallback(null);
number = 123, text = Hello world
The Zig-to-PHP bridge sits in manually managed memory. When it's no longer needed you have
to free it using zigar.function.release(). Besides releasing
memory on the Zig side, doing so also removing the reference on the PHP callback, allowing
it to be garbage-collected eventually. If the function given is an ordinary Zig function (which
callback points to initially) release() does nothing.
Taking advantage of Zigar's auto-vification mechanism, you generally don't need to explicitly create the function object:
<?php
$m = zigar_use(__DIR__ . '/php-fn-example-2.zig');
function hello($number, $text) {
echo "number = $number, text = $text\n";
}
$m->setCallback('hello');
$m->runCallback();
$m->setCallback(null);
number = 123, text = Hello world
Anonymous functions are acceptable as argument:
<?php
$m = zigar_use(__DIR__ . '/javascript-fn-example-2.zig');
$global = "some value";
$m->setCallback(function($number, $text) use($global) {
echo "number = $number, text = $text, global = $global\n";
});
$m->runCallback();
$m->setCallback(null);
number = 123, text = Hello world, global = some value
Basically, anything that is_callable() would report true on will work:
<?php
$m = zigar_use(__DIR__ . '/javascript-fn-example-2.zig');
class Something {
function __construct($arg) {
$this->arg = $arg;
}
static function static_fn($number, $text) {
echo "static: number = $number, text = $text\n";
}
function method($number, $text) {
echo "instance: number = $number, text = $text, arg = $this->arg\n";
}
function __invoke($number, $text) {
echo "magic: number = $number, text = $text, arg = $this->arg\n";
}
}
$instance = new Something("foobar");
$m->setCallback([ 'Something', 'static_fn' ]);
$m->runCallback();
$m->setCallback([ $instance, 'method' ]);
$m->runCallback();
$m->setCallback($instance);
$m->runCallback();
$m->setCallback(null);
static: number = 123, text = Hello world
instance: number = 123, text = Hello world, arg = foobar
magic: number = 123, text = Hello world, arg = foobar
Allocator
An allocator can be passed to the PHP side when the function is expected to return variable-length data. Consult its documentation for details.
Async operation
Zig code can receive data from JavaScript asynchronously using Promise and Generator. Examples can be found in their respected pages.