codecamp

PHP8 基础 FFI 用法

在深入了解 FFI API 细节之前,先看几个示例,展示 FFI API 在常规任务中的简单使用。

注意:其中一些示例需要 libc.so.6,因此在没有该库的系统上无法运行。

示例 #1 从共享库中调用函数

<?php
// 创建 FFI 对象,加载 libc 和输出函数 printf()
$ffi = FFI::cdef(
"int printf(const char *format, ...);", // 这是普遍的 C 声明
"libc.so.6");
// call C's printf()
$ffi->printf("Hello %s!\n", "world");
?>

以上示例会输出:

Hello world!
注意:请注意,一些 C 函数需要特定的调用规则,例如 __fastcall、__stdcall 或 __vectorcall。

示例 #2 调用函数,通过参数返回结构体

<?php
// 创建 gettimeofday() 绑定
$ffi = FFI::cdef("
typedef unsigned int time_t;
typedef unsigned int suseconds_t;

struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};

struct timezone {
int tz_minuteswest;
int tz_dsttime;
};

int gettimeofday(struct timeval *tv, struct timezone *tz);
", "libc.so.6");
// 创建 C 数据结构
$tv = $ffi->new("struct timeval");
$tz = $ffi->new("struct timezone");
// 调用 C 的 gettimeofday()
var_dump($ffi->gettimeofday(FFI::addr($tv), FFI::addr($tz)));
// 访问 C 数据结构的字段
var_dump($tv->tv_sec);
// 打印完整数据结构
var_dump($tz);
?>

以上示例的输出类似于:

int(0)
int(1555946835)
object(FFI\CData:struct timezone)#3 (2) {
  ["tz_minuteswest"]=>
  int(0)
  ["tz_dsttime"]=>
  int(0)
}

示例 #3 访问已存在的 C 变量

<?php
// 创建 FFI 对象,加载 libc 和输出 errno 变量
$ffi = FFI::cdef(
"int errno;", // 这是普遍的 C 声明
"libc.so.6");
// print C's errno
var_dump($ffi->errno);
?>

以上示例会输出:

int(0)

示例 #4 创建和修改 C 变量

<?php
// 创建新的 C int 变量
$x = FFI::new("int");
var_dump($x->cdata);

// 简单赋值
$x->cdata = 5;
var_dump($x->cdata);

// 复合赋值
$x->cdata += 2;
var_dump($x->cdata);
?>

以上示例会输出:

int(0)
int(5)
int(7)

示例 #5 使用 C 数组

<?php
// 创建 C 数据结构
$a = FFI::new("long[1024]");
// 使用它就像使用常规数组
for ($i = 0; $i < count($a); $i++) {
$a[$i] = $i;
}
var_dump($a[25]);
$sum = 0;
foreach ($a as $n) {
$sum += $n;
}
var_dump($sum);
var_dump(count($a));
var_dump(FFI::sizeof($a));
?>

以上示例会输出:

int(25)
int(523776)
int(1024)
int(8192)

示例 #6 使用 C 枚举

<?php
$a = FFI::cdef('typedef enum _zend_ffi_symbol_kind {
ZEND_FFI_SYM_TYPE,
ZEND_FFI_SYM_CONST = 2,
ZEND_FFI_SYM_VAR,
ZEND_FFI_SYM_FUNC
} zend_ffi_symbol_kind;
');
var_dump($a->ZEND_FFI_SYM_TYPE);
var_dump($a->ZEND_FFI_SYM_CONST);
var_dump($a->ZEND_FFI_SYM_VAR);
?>

以上示例会输出:

int(0)
int(2)
int(3)


PHP8 预定义常量
PHP8 回调
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

PHP8 语言参考

PHP8 函数参考

PHP8 影响 PHP 行为的扩展

PHP8 Componere

PHP8 安装/配置

PHP8 外部函数接口

PHP8 选项和信息

PHP8 选项/信息 函数

PHP8 Windows Cache for PHP

PHP8 WinCache 函数

PHP8 Yac

PHP8 身份认证服务

PHP8 Radius 函数

PHP8 压缩与归档扩展

PHP8 Phar

PHP8 Zip

PHP8 ZipArchive 类

PHP8 加密扩展

PHP8 OpenSSL

PHP8 OpenSSL 函数

PHP8 Sodium 函数

PHP8 数据库扩展

PHP8 针对各数据库系统对应的扩展

PHP8 CUBRID 函数

PHP8 Firebird/InterBase

PHP8 Firebird/InterBase函数

PHP8 MongoDB介绍驱动程序体系结构和特殊功能

PHP8 MongoDB\Driver\Command 类

PHP8 MongoDB\Driver\Query 类

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }