function mycheck($person, $expected) { $debug = 0; # Normal target language polymorphic call $ret = $person->id(); if ($debug) { print $ret . "\n"; } check::equal($ret, $expected, "#1 failed"); # Polymorphic call from C++ $caller = new Caller(); $caller->setCallback($person); $ret = $caller->call(); if ($debug) { print $ret . "\n"; } check::equal($ret, $expected, "#2 failed"); # Polymorphic call of object created in target language and passed to # C++ and back again $baseclass = $caller->baseClass(); $ret = $baseclass->id(); if ($debug) { print $ret . "\n"; } # TODO: Currently we do not track the dynamic type of returned # objects, so in case it's possible that the dynamic type is not equal # to the static type, we skip this check. if (get_parent_class($person) === false) { check::equal($ret, $expected, "#3 failed"); } $caller->resetCallback(); if ($debug) { print "----------------------------------------\n"; } }
require "example.php"; # Class, which overwrites Callback::run(). class PhpCallback extends Callback { function run() { print "PhpCallback.run()\n"; } } # Create an Caller instance $caller = new Caller(); # Add a simple C++ callback (caller owns the callback, so # we disown it first by clearing the .thisown flag). print "Adding and calling a normal C++ callback\n"; print "----------------------------------------\n"; $callback = new Callback(); $callback->thisown = 0; $caller->setCallback($callback); $caller->call(); $caller->delCallback(); print "\n"; print "Adding and calling a PHP callback\n"; print "------------------------------------\n"; # Add a PHP callback. $callback = new PhpCallback(); $callback->thisown = 0; $caller->setCallback($callback); $caller->call(); $caller->delCallback(); # All done. print "php exit\n";
$thread = new Caller($method, $params); if ($thread->start()) { return $thread; } } /** * Do whatever, result stored in $this->result, don't try to join twice **/ public function __toString() { if (!$this->joined) { $this->joined = true; $this->join(); } return $this->result; } private $method; private $params; private $result; private $joined; } /* here's us calling file_get_contents in a thread of it's own */ $future = Caller::call("file_get_contents", array("http://www.php.net")); /* here's us counting the bytes out, note, __toString() magic joined so no need to join explicitly */ printf("Got %d bytes from php.net\n", strlen((string) $future)); /* you can reference again as a string because you cached the result, YOU CANNOT JOIN TWICE */ printf("First 16 chars: %s\n", substr((string) $future, 0, 16)); /* here's us calling a closure in a thread of it's own */ $future = Caller::call(function ($params) { printf("and how about this: %s, %s %s %s %s!\n", ...$params); }, [["also", "you", "can", "use", "closures"]]);
public static function call($method, $params) { $thread = new Caller($method, $params); if ($thread->start()) { return $thread; } /** else throw Nastyness **/ } /** * Do whatever, result stored in $this->result, don't try to join twice **/ public function __toString() { if (!$this->joined) { $this->joined = true; $this->join(); } return $this->result; } } /* here's us calling file_get_contents in a thread of it's own */ $future = Caller::call("file_get_contents", array("http://www.php.net")); /* here's us counting the bytes out, note, __toString() magic joined so no need to join explicitly */ printf("Got %d bytes from php.net\n", strlen((string) $future)); /* you can reference again as a string because you cached the result, YOU CANNOT JOIN TWICE */ printf("First 16 chars: %s\n", substr((string) $future, 0, 16)); /* if you have no __toString(): */ /* $response = $future->result; */ /* you could also not use a reference to the thread, if the threads job was to say, log stats and you do not need to know when or how it returns, then you could just Async::call at the beginning of the request and by the end it would be finished */