承接 symplely/zend-ffi 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

symplely/zend-ffi

Composer 安装命令:

composer create-project symplely/zend-ffi

包简介

Provides the base API for creating extensions, or modifying Zend/PHP internal core with FFI.

README 文档

README

zend-ffi tests

Provides the base API for creating extensions, or modifying Zend/PHP internal core with FFI.

  • For PHP 7.4, 8.0, 8.1, 8.2, Windows, Mac, Linux

It allows loading of shared libraries (.dll or .so), calling of C functions and accessing of C type data structures in pure PHP.

This package breaks down the Zend extension API into PHP classes getting direct access to all PHP internal actions. You can actually change PHP default behaviors. You will be able to get the behavior of componere extension without needing it.

Many routines here is a rewrite of Z-Engine library package that use different terminology and setup structure. This package follow/keep PHP C source code style with a skeleton FFi installation process.

There are many extensions on Pecl that hasn't been updated.

Installation

For normal standalone usage.

    composer require symplely/zend-ffi

To setup a skeleton for FFI integration.

    composer create-project symplely/zend-ffi .

Minimum php.ini setting:

extension=ffi
extension=openssl
extension=sockets

zend_extension=opcache

[opcache]
; Determines if Zend OPCache is enabled
opcache.enable=1

; Determines if Zend OPCache is enabled for the CLI version of PHP
opcache.enable_cli=1

[ffi]
; FFI API restriction. Possible values:
; "preload" - enabled in CLI scripts and preloaded files (default)
; "false"   - always disabled
; "true"    - always enabled
ffi.enable="true"

; List of headers files to preload, wildcard patterns allowed. `ffi.preload` has no effect on Windows.
; See headers directory for `your-php-version`, this feature is untested, since not enabled for Windows.
;ffi.preload=path/to/vendor/symplely/zend-ffi/headers/ze(your-php-version).h

;This feature is untested.
;opcache.preload==path/to/vendor/symplely/zend-ffi/preload.php

For a simple FFI integration process create/edit:

  • ffi_extension.json each package/library should list the files to preload, will be process by ffi_preloader.php script.
  • .ignore_autoload.php will be called/executed by composer create-project your_package .cdef/foldername event.
    • This event is only called when your package is installed by composer create-project command.
  • .preload.php for general common FFI functions to be used, change the tag_changeMe skeleton name.
  • .github\workflows\*.yml these GitHub Actions is designed for cross-compiling and committing the binary back to your repo, change some_lib and some_repo skeleton names.
    • The idea of this is to make installation totally self-contained, the necessary third party library binary is bundled in.
    • The CI build Actions is setup for manually runs only.
// Skeleton for `ffi_extension.json` file
{   // The same name to be used in `composer create-project package .cdef/foldername`
    "name": "foldername",
    // Either
    "preload": {
        "files": [
            "path/to/file.php",
            "...",
            "..."
        ],
    // Or
        "directory": [
            "path/to/directory"
        ]
    }
}

Documentation

The functions in preload.php and Functions.php should be used or expanded upon.

See tests folder for examples. Copy/paste the code between --FILE-- and --EXPECT-- blocks in the .phpt files.

For general FFI C data handling see CStruct class.

Functions c_int_type(), c_struct_type(), c_array_type() and c_typedef() are wrappers for any C data typedef turning it into PHP CStruct class instance, with all FFI functions as methods with additional features.

For AST handling:

  • zend_parse_string() will convert PHP source code into native C data zend_ast node held in ZendAst class, use print_ast() to display results.
  • zend_ast_process(function(\ZE\AstProcess $hook){}) to intercept and modify AST after compilation process.

Get the behavior of PHP extensions like nikic/php-ast and sgolemon/astkit that provide low-level bindings to the underlying AST structures, without any addition library.

The whole PHP lifecycle process can be achieved by just extending StandardModule abstract class.

declare(strict_types=1);

require 'vendor/autoload.php';

final class SimpleCountersModule extends \StandardModule
{
    protected string $module_version = '0.4';

    //Represents ZEND_DECLARE_MODULE_GLOBALS macro.
    protected string $global_type = 'unsigned int[10]';

    // Do module startup?
    protected bool $m_startup = true;
    protected bool $r_startup = true;

    // Represents PHP_MINIT_FUNCTION() macro.
    public function module_startup(int $type, int $module_number): int
    {
        echo 'module_startup' . \PHP_EOL;
        return \ZE::SUCCESS;
    }

    // Represents PHP_RINIT_FUNCTION() macro.
    public function request_startup(...$args): int
    {
        echo 'request_startup' . \PHP_EOL;
        $data = $this->get_globals();
        $data[5] = 25;
        return \ZE::SUCCESS;
    }

    // Represents PHP_GINIT_FUNCTION() macro.
    public function global_startup(\FFI\CData $memory): void
    {
        if (\PHP_ZTS) {
            \tsrmls_activate();
        }

        echo 'global_startup' . \PHP_EOL;
        \FFI::memset($this->get_globals(), 0, $this->globals_size());
    }
}

$module = new SimpleCountersModule();
if (!$module->is_registered()) {
    $module->register();
    $module->startup();
}

// Represents ZEND_MODULE_GLOBALS_ACCESSOR() macro.
$data = $module->get_globals();
$module->get_globals('4', 20);
$data[0] = 5;
$data[9] = 15;
var_dump($data);

ob_start();
phpinfo(8);
$value = ob_get_clean();

preg_match('/simple_counters support => enabled/', $value, $matches);
var_dump($matches[0]);

A hack for headers_sent() like errors: PHP Warning: Cannot modify header information - headers already sent by (output started at xxxxxxxx

require 'vendor/autoload.php';

function headers_sent_reset()
{
    zend_sg('headers_sent', 0);
}

echo 'any non-buffered output';
var_dump(headers_sent()); // true

headers_sent_reset();
var_dump(headers_sent()); // false

// This would have otherwise produced warning/errors!
header('Location: http://www.example.com/');

To create proper FFI C library headers from any C ABI library *.h file

Linux: cpp -P -D"__attribute__(ARGS)=" path/to/original/header.h -o ffi_header.h Windows: First download mcpp mcpp -P -D"__attribute__(ARGS)=" path/to/original/header.h -o ffi_header.h

The option -I <directory> might be needed to search/find additional include sources, and the output file will still need editing, mostly 96% proper headers, FFI will complain, just edit/check the 2 lines after the indicated line.

Reference/Credits

Possible Security Risks

The Beginning

Contributing

Contributions are encouraged and welcome; I am always happy to get feedback or pull requests on Github :) Create Github Issues for bugs and new features and comment on the ones you are interested in.

License

The MIT License (MIT). Please see License File for more information.

symplely/zend-ffi 适用场景与选型建议

symplely/zend-ffi 是一款 基于 C 开发的 Composer 扩展包,目前已累计 2.38k 次下载、GitHub Stars 达 13, 最近一次更新时间为 2022 年 09 月 06 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「api」 「extensions」 「core」 「ext」 「cdata」 「ffi」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 symplely/zend-ffi 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 symplely/zend-ffi 我们能提供哪些服务?
定制开发 / 二次开发

基于 symplely/zend-ffi 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2.38k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 13
  • 点击次数: 19
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 13
  • Watchers: 2
  • Forks: 3
  • 开发语言: C

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-09-06