Skip to content

Commit

Permalink
Merge branch 'main' into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
TheTechsTech committed Feb 18, 2023
2 parents 2d1cff1 + a2745f0 commit a55dd1d
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 107 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ opcache.enable_cli=1
ffi.enable="true"

; List of headers files to preload, wildcard patterns allowed. `ffi.preload` has no effect on Windows.
ffi.preload=path/to/vendor/symplely/zend-ffi/headers/ze{%php version%}_vendor.h
;ffi.preload=path/to/vendor/symplely/zend-ffi/headers/ze(your-php-version)_vendor.h

opcache.preload==path/to/vendor/symplely/zend-ffi/preload.php
;opcache.preload==path/to/vendor/symplely/zend-ffi/preload.php
```

For a simple FFI integration process **create/edit**:
Expand Down
2 changes: 1 addition & 1 deletion tests/015-stack_resources_fd.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $fd = fopen(__FILE__, 'r');
var_dump($fd);
$int_fd = \get_fd_resource($fd);
var_dump($int_fd);
var_dump(create_resource_fd($int_fd));
var_dump(create_resource_fd($int_fd, new \stdClass));
[$zval, $fd1] = \zval_to_fd_pair($fd);
var_dump($zval, $fd1);
var_dump(\get_resource_fd($fd1));
Expand Down
81 changes: 70 additions & 11 deletions zend/Functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,14 @@ function zval_is_dtor(object $instance): bool
/**
* Returns an _instance_ that's a cross platform representation of a file handle.
*
* @param string $type platform file `typedef` handle.
* @param string $type platform _file descriptor_ handle to create, example: `php_socket_t`.
* @param bool $create `false` to stop `cdata` creation.
* - Use to return an class instance with no `cdata` object.
* @return Resource
*/
function fd_type(string $type = 'uv_file'): Resource
function fd_type(string $type = 'uv_file', bool $create = true): Resource
{
return Resource::init($type);
return Resource::init($type, $create);
}

/**
Expand Down Expand Up @@ -372,15 +374,50 @@ function create_resource(CData $fd_ptr, string $type = 'stream', int $module = \
}

/**
* Create `resource` from `int`, _bind_ to an **CData** `object`.
* Same as `get_resource_fd()`, but holds reference to an `object`.
* - This returns the static held reference in ZE `Resource` class, or creates one.
*
* @param integer $fd
* @param object $extra
* @param object $store
* @return resource
*/
function create_resource_fd(int $fd, object $extra = null)
function create_resource_fd(int $fd, object $store = null)
{
return PhpStream::fd_to_zval($fd, 'wb+', false, $extra);
return PhpStream::fd_to_zval($fd, 'wb+', false, $store);
}

/**
* Create and register `resource` from **CData** `object`, _bind_ to `int` **fd**.
* - by way of `zend_register_resource()`.
* - This will also create static held reference in ZE `Resource` class.
*
* @param integer $fd
* @param object $cdata PHP `__invoke()` instance that returns `CData`
* @param string $type resource string type
* @param callable $rsrc
* @return resource
*/
function create_resource_object(int $fd, object $cdata, string $type = 'stream', callable $rsrc = null)
{
$object_ptr = $cdata();
$object_res = \zend_register_resource(
$object_ptr,
\zend_register_list_destructors_ex((\is_null($rsrc)
? function (CData $rsrc) {
} : $rsrc),
null,
$type,
\ZEND_MODULE_API_NO
)
);

$object_zval = \zval_resource($object_res);
$resource = \zval_native($object_zval);
$file = \fd_type('', false);
$file->add_object($cdata);
$file->add_fd_pair($fd, $resource);

return $resource;
}

function zend_reference(&$argument): ZendReference
Expand Down Expand Up @@ -447,34 +484,37 @@ function zval_blank(): Zval
}

/**
* - This returns the static held reference in ZE `Resource` class, or creates one.
* @param resource $stream
* @return array<Zval|uv_file|int>
*/
function zval_to_fd_pair($stream): array
function zval_to_fd_pair($stream, string $typedef = 'php_socket_t'): array
{
$zval = \zval_constructor($stream);
$fd = PhpStream::zval_to_fd($zval);
$fd = PhpStream::zval_to_fd($zval, $typedef);

return [$zval, $fd];
}

/**
* Return `int` of _file descriptor_ from a **resource**, after converting into/from `php_stream` C struct.
* - This returns the static held reference in ZE `Resource` class, or creates one.
*
* @param resource|int $fd
* @return int|uv_file `fd`
*/
function get_fd_resource($fd): int
function get_fd_resource($fd, string $typedef = 'php_socket_t'): int
{
if (!\is_resource($fd) && !\is_integer($fd))
return \ze_ffi()->zend_error(\E_WARNING, "only resource or int types allowed");

return PhpStream::zval_to_fd(\zval_constructor($fd));
return PhpStream::zval_to_fd(\zval_constructor($fd), $typedef);
}

/**
* Remove/free any `resource` created with `get_resource_fd()`, `get_fd_resource()`,
* `get_socket_fd()`, or `zval_to_fd_pair()`.
* - This removes the static held reference from ZE `Resource` class.
*
* @param resource|int|Zval $fd_Int_Zval
* @return void
Expand All @@ -495,8 +535,26 @@ function remove_fd_resource(...$fd_Int_Zval): void
}
}

/**
* Returns any `resource` created with `get_resource_fd()`, `get_fd_resource()`, `get_socket_fd()`,
* `create_resource_object()`, `create_resource_fd()` or `zval_to_fd_pair()`.
* - This returns the static held reference in ZE `Resource` class.
*
* @param integer $handle
* @param boolean $get_int
* @param boolean $get_pair
* @param boolean $get_instance
*
* @return Resource|int|array|CData|null
*/
function resource_get_fd(int $handle, bool $get_int = true, bool $get_pair = false, bool $get_instance = false)
{
return Resource::get_fd($handle, $get_int, $get_pair, $get_instance);
}

/**
* Return `resource` from `int` a _file descriptor_, after converting into/from `php_stream` C struct.
* - This returns the static held reference in ZE `Resource` class, or creates one.
*
* @param int $fd
* @param string $mode
Expand All @@ -510,6 +568,7 @@ function get_resource_fd($fd, string $mode = 'wb+', bool $getZval = false)

/**
* Return `int` of _file descriptor_ from a **socket**, after converting into/from `php_socket` C struct.
* - This returns the static held reference in ZE `Resource` class, or creates one.
*
* @param resource|int|\Socket $fd
* @return php_socket_t|int
Expand Down
36 changes: 29 additions & 7 deletions zend/StandardModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,24 +215,46 @@ final public function module_destructor(): void
$this->global_rsrc = null;
}

$this->ze_other_ptr = null;
$this->ze_other = null;
$this->reflection = null;
if (!$this->module_destructor_linked)
static::set_module(null);

\zend_hash_delete($this->module_name);
static::clear_module();
}
}

final protected static function set_module(?\StandardModule $module): void
final protected static function set_module(\StandardModule $module): void
{
if (\PHP_ZTS)
self::$global_module[\ze_ffi()->tsrm_thread_id()] = $module;
else
self::$global_module[static::class] = $module;
}

/**
* Force clear and shutdown module.
* - Will cause `PHP_MSHUTDOWN_FUNCTION()` and `PHP_GSHUTDOWN_FUNCTION()` to execute.
*
* @return void
*/
final public static function clear_module(): void
{
/** @var static */
$module = (\PHP_ZTS)
? self::$global_module[\ze_ffi()->tsrm_thread_id()]
: self::$global_module[static::class];

if (!\is_null($module)) {
if (\PHP_ZTS)
self::$global_module[\ze_ffi()->tsrm_thread_id()] = null;
else
self::$global_module[static::class] = null;

\zend_hash_delete($module->module_name);
$module->ze_other_ptr = null;
$module->ze_other = null;
$module->reflection = null;
\zval_del_ref($module);
}
}

/**
* Represents `ZEND_GET_MODULE()` _macro_.
*
Expand Down
48 changes: 24 additions & 24 deletions zend/Types/PhpStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
if (!\class_exists('PhpStream')) {
final class PhpStream extends Resource
{
public static function init(string $type = null): self
public static function init(string $type = 'php_socket_t', bool $create = true): self
{
return new static('struct _php_stream', false);
return new static('struct _php_stream', $create);
}

/**
Expand Down Expand Up @@ -87,27 +87,27 @@ public static function open_wrapper(
* @param bool $getZval
* @return resource|Zval|null
*/
public static function fd_to_zval($fd, $mode = 'wb+', bool $getZval = false, object $extra = null)
public static function fd_to_zval($fd, $mode = 'wb+', bool $getZval = false, object $store = null)
{
$stream = Resource::get_fd($fd, true);
if ($stream instanceof Zval) {
$stream = \resource_get_fd($fd, false, true);
if (\is_array($stream)) {
if ($getZval)
return $stream;
return \zval_constructor($stream[1]);

return \zval_native($stream);
return $stream[1];
}

$stream = \ze_ffi()->_php_stream_fopen_from_fd($fd, $mode, null);
$resource = null;
try {
$zval = PhpStream::init_stream($stream);
$resource = \zval_native($zval);
$php_stream = \fd_type();
$php_stream->update(\ffi_null(), true);
if (!\is_null($extra))
$php_stream->add_object($extra);
$php_stream = \fd_type('', false);
$php_stream->update($stream, true);
if (!\is_null($store))
$php_stream->add_object($store);

$php_stream->add_pair($zval, $fd, (int)$resource);
$php_stream->add_fd_pair($fd, $resource);
} catch (\Throwable $e) {
return \ze_ffi()->_php_stream_free($stream, self::PHP_STREAM_FREE_CLOSE);
}
Expand Down Expand Up @@ -142,9 +142,9 @@ public static function php_stream_from_res(ZendResource $res): ?PhpStream
return !\is_cdata($stream) ? null : static::init_value($stream);
}

protected static function to_descriptor(Zval $ptr)
protected static function to_descriptor(Zval $ptr, string $type = 'php_socket_t')
{
$zval_fd = \fd_type();
$zval_fd = \fd_type($type);
$fd = $zval_fd();
$stream = \ze_ffi()->cast(
'php_stream*',
Expand Down Expand Up @@ -177,17 +177,17 @@ protected static function to_descriptor(Zval $ptr)
* @param Zval $ptr
* @return int|uv_file `fd`
*/
public static function zval_to_fd(Zval $ptr): int
public static function zval_to_fd(Zval $ptr, string $typedef = 'php_socket_t'): int
{
$fd = -1;
$type = $ptr->macro(\ZE::TYPE_P);
if ($type === \ZE::IS_RESOURCE) {
$handle = $ptr()->value->res->handle;
$zval = Resource::get_fd($handle, true);
if ($zval instanceof Zval)
return Resource::get_fd($handle, false, false, true);
$fd = \resource_get_fd($handle);
if (!\is_null($fd))
return $fd;

$zval_fd = static::to_descriptor($ptr);
$zval_fd = static::to_descriptor($ptr, $typedef);
$fd = \is_null($zval_fd) ? -1 : $zval_fd();
} elseif ($type === \ZE::IS_LONG) {
$fd = $ptr->macro(\ZE::LVAL_P);
Expand All @@ -199,7 +199,7 @@ public static function zval_to_fd(Zval $ptr): int

if (\is_cdata($fd)) {
$fd = $fd[0];
$zval_fd->add_pair($ptr, $fd, $handle);
$zval_fd->add_fd_pair($fd, $ptr);
}

return $fd;
Expand Down Expand Up @@ -237,9 +237,9 @@ public static function zval_to_fd_select(Zval $ptr, string $fd_type = 'php_socke
// Validate Checks
if ($ptr->macro(\ZE::TYPE_P) === \ZE::IS_RESOURCE) {
$handle = $ptr()->value->res->handle;
$zval = Resource::get_fd($handle, true);
if ($zval instanceof Zval)
return Resource::get_fd($handle, false, false, true);
$fd = \resource_get_fd($handle);
if (!\is_null($fd))
return $fd;

$zval_fd = \fd_type($fd_type);
$fd = $zval_fd();
Expand Down Expand Up @@ -287,7 +287,7 @@ public static function zval_to_fd_select(Zval $ptr, string $fd_type = 'php_socke

if (\is_cdata($fd)) {
$fd = $fd[0];
$zval_fd->add_pair($ptr, $fd, $handle);
$zval_fd->add_fd_pair($fd, $ptr);
} elseif ($fd === -1) {
unset($zval_fd);
}
Expand Down
Loading

0 comments on commit a55dd1d

Please sign in to comment.