Loading... # [PHP 8.0 中的 FFI 扩展:将各种语言的库集成到 PHP 中](https://mp.weixin.qq.com/s/n8UHf-_QltlhWvKBpqgoxQ) 随着技术的发展,我们常常会遇到需要使用多种不同编程语言的场景。在过去,我们通常需要一个中间人,比如数据库或 API 网关,来协调这些不同的语言之间的交互。但是,现在在 PHP 8.0 中,我们有了一个新的方式来集成这些语言,这就是 FFI 扩展。 所谓 FFI,全称为 Foreign Function Interface,它提供了一种直接在 PHP 代码中调用其他语言的库的方式。这种方式不仅方便,而且会显著提高程序的性能。FFI 扩展允许我们在 PHP 中使用 C、C ++、Rust、Golang 或 Swift 等语言编写的库,而不需要编写任何扩展或共享库。 在本文中,我们将介绍 FFI 扩展的基本特性、为什么要使用它以及如何将 C 语言的库集成到 PHP 8.0 中。我们将学习如何编写 C 代码并将其编译成共享库,然后使用 FFI 扩展来加载它,调用其中的函数并处理返回值。 ## FFI 扩展的基本特性 FFI 扩展是在编译 PHP 时包含的默认扩展,因此我们无需安装任何其他东西。它还提供了以下一些功能: - 声明并调用 C 函数:我们可以使用 FFI 扩展声明并调用 C 函数,而无需编写任何 C 扩展和共享库。这使得 PHP 8.0 更加多语言友好,可以轻松地集成其他语言的库。 - 自动类型转换:FFI 扩展允许我们在 PHP 8.0 中使用和 C 语言中相同的数据类型,比如指针、结构体和联合体,这些类型将在 PHP 中自动转换为对应的类型。 - 动态库加载:FFI 扩展可以加载动态链接库(共享库)和静态库,以便在 PHP 8.0 中使用它们。 - 可生成绑定:FFI 扩展可以生成 PHP 类型、方法和常量的绑定。这些绑定将根据所加载的库自动生成,无需编写手动绑定。 ## 为什么要使用 FFI 扩展 使用 FFI 扩展的主要好处在于它可以让我们轻松地将其他语言编写的代码集成到 PHP 8.0 中。这些代码可能包括精密的算法、高速的数据结构、图形渲染器或其他一些高性能任务。 另一个优点是,在使用 FFI 扩展时,我们无需编写任何扩展或共享库,从而节省了时间和精力。我们只需声明函数并将库加载到 PHP 中,然后就可以轻松调用它们。 最后,FFI 扩展还提供了对 C 语言中的数据类型和特性的支持。因此,如果我们希望在 PHP 8.0 中调用包含 C 语言中定义的结构体或共用体的函数,则 FFI 扩展将是一种特别实用的方法。 ## 将 C 语言的库集成到 PHP 中 下面,我们将展示如何在 PHP 8.0 中使用 FFI 扩展,将 C 语言的库集成到 PHP 中。这个例子将使用一个简单的数学库,该库包含两个函数,分别将两个整数相加并返回其和,以及将两个整数相减并返回其差。 ### 1. 编写 C 代码并将其编译为共享库 首先,我们需要编写一个简单的 C 函数来添加和减去两个数,并将其编译成共享库。这个示例代码位于 `addsub.c` 文件中: ```c #include <stdio.h> int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } ``` 然后,我们将使用 GCC(GNU 编译器集合)来将代码编译成共享库。在终端中运行以下命令来编译代码: ```bash gcc -c addsub.c gcc -shared -o libaddsub.so addsub.o ``` 这将使用 gcc 编译器和 `-c` 标志来将源代码编译为目标文件,并使用 `-shared` 标志将文件打包在一起,形成 `libaddsub.so` 共享库。 ### 2. 在 PHP 中使用 FFI 扩展加载共享库 接下来,我们需要在 PHP 8.0 中使用 FFI 扩展来加载该共享库并调用其中的函数。我们将在 `math.php` 文件中进行操作: ```php <?php // 定义 struct in6_addr FFI::cdef(" typedef unsigned char u_int8_t; typedef struct in6_addr { union { u_int8_t __u6_addr8[16]; uint16_t __u6_addr16[8]; uint32_t __u6_addr32[4]; } __in6_u; } in6_addr; "); // 加载共享库 $ffi = FFI::load("./libaddsub.so"); // 调用共享库中的函数 $a = 10; $b = 5; $c = $ffi->add($a, $b); $d = $ffi->sub($a, $b); // 输出结果 echo "$a + $b = $c\n"; echo "$a - $b = $d\n"; ``` 在这个例子中,我们首先使用 `FFI::cdef` 函数定义了一个 `struct in6_addr` 类型,它在 C 语言代码中定义了一个 IPv6 地址的结构体。在我们的示例中,这里仅作为演示。 然后,我们使用 `FFI::load` 函数加载共享库 `libaddsub.so`。请确保该文件位于您的 PHP 文件的同一目录下,否则请提供其完整路径。 最后,我们使用 `$ffi->add` 和 `$ffi->sub` 调用共享库中的函数,并将它们的返回值分别存储在 `$c` 和 `$d` 变量中。然后,我们使用 `echo` 语句将结果输出到终端。 ### 3. 在终端中运行脚本 现在,我们已经准备好在终端中运行该脚本了。在终端中,我们导航至 PHP 文件所在目录,并运行以下命令: ```php php math.php ``` 这将启动 PHP 解释器并执行 `math.php` 文件中的代码。因此,您应该看到以下输出: ```php 10 + 5 = 15 10 - 5 = 5 ``` 这表明我们的代码成功将 C 语言的库集成到 PHP 中,并在 PHP 中调用了 C 函数。 ## 结论 在本文中,我们探讨了 PHP 8.0 中的 FFI 扩展及其基本特性。我们看到,FFI 扩展可以轻松地将其他语言编写的库集成到 PHP 中,而无需编写任何扩展或共享库。我们还探讨了如何编写 C 代码并将其编译为共享库,然后使用 FFI 扩展在 PHP 8.0 中加载该库并调用其中的函数。 使用 FFI 扩展可能会为我们带来很多好处,特别是当我们需要在 PHP 8.0 中使用一些包含 C 符号的库时。因此,我建议您在更多的场景中尝试使用 FFI 扩展,以便发掘其更多的优点。 最后修改:2023 年 12 月 29 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏