zephir mysql_PHP7.4 全新扩展方式 FFI 详解

本文介绍了如何使用PHP7.4的FFI(Foreign Function Interface)特性来直接调用C语言的libcurl库,从而抓取网页内容。相比传统的PHP curl扩展,FFI提供了更直接调用C库的便利。通过FFI,开发者无需编写C语言的扩展,只需在PHP脚本中定义函数原型并调用。示例中详细展示了使用FFI调用libcurl进行HTTP请求的步骤,包括定义函数原型、设置选项、执行请求等,并对比了传统curl扩展的使用方式。最后,文章提到了FFI在性能和安全方面的考虑,以及如何通过预加载(opcache.preload)进一步优化。
摘要由CSDN通过智能技术生成

随着PHP7.4而来的有一个我认为非常有用的一个扩展:PHP FFI(Foreign Function interface),引用一段PHP FFI RFC中的一段描述

官方群点击此处。For PHP, FFI opens a way to write PHP extensions and bindings to C libraries in pure PHP.

是的,FFI提供了高级语言直接的互相调用,而对于PHP而言,FFI让我们可以方便的调用C语言写的各种库。

其实现有大量的PHP扩展是对一些已有的C库的包装,某些常用的mysqli,curl,gettext等,PECL中也有大量的类似扩展。

传统的方式,当我们需要用一些已有的C语言的库的能力的时候,我们需要用C语言写包装器,把他们包装成扩展,这个过程中就需要大家去学习PHP的扩展怎么写,当然现在也有一些方便的方式,某种Zephir。但总还是有一些学习成本的,而有了FFI之后,我们就可以直接在PHP脚本中调用C语言写的库中的函数了。

而C语言几十年的历史中,积累积累的优秀的库,FFI直接让我们可以方便的享受这个庞大的资源了。

言归正传,今天我用一个例子来介绍,我们如何使用PHP来调用libcurl,来抓取一个网页的内容,为什么要用libcurl呢?PHP不是已经有了curl扩展了么?嗯,首先因为libcurl的api我比较熟,其次呢,正是因为有了,才好对比,传统扩展方式AS和FFI方式直接的易用性不是?

首先,某些我们就拿当前你看的这篇文章为例,我现在需要写一段代码来抓取它的内容,如果用传统的PHP的curl扩展,我们大概会这么写:

$url = "https://www.laruence.com/2020/03/11/5475.html";

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

curl_exec($ch);

curl_close($ch);

(因为我的网站是https的,所以会多一个设置SSL_VERIFYPEER的操作)那如果是用FFI呢?

首先要启用PHP7.4的ext / ffi,需要注意的是PHP-FFI要求libffi-3以上。

然后,我们需要告诉PHP FFI我们要调用的函数原型是咋样的,这个我们可以使用FFI :: cdef,它的原型是:

FFI::cdef([string $cdef = "" [, string $lib = null]]): FFI

在字符串$cdef中,我们可以写C语言函数式申明,FFI会parse它,了解到我们要在字符串$lib这个库中调用的函数的签名是啥样的,在这个例子中,我们用到三一个libcurl的函数,它们的申明我们都可以在libcurl的文档里找到,某些关于curl_easy_init。

具体到这个例子,我们写一个curl.php,包含所有要申明的东西,代码如下:

$libcurl = FFI::cdef(<<

void *curl_easy_init();

int curl_easy_setopt(void *curl, int option, ...);

int curl_easy_perform(void *curl);

void curl_easy_cleanup(void *handle);

CTYPE

, "libcurl.so"

);

这里有个地方是,文档中写的是返回值是CURL *,但事实上因为我们的示例中不会解引用它,只是传递,那就避免麻烦就用void *代替。

然而还有个麻烦的事情是,PHP预定义好了:

const CURLOPT_URL = 10002;

const CURLOPT_SSL_VERIFYPEER = 64;

$libcurl = FFI::cdef(<<

void *curl_easy_init();

int curl_easy_setopt(void *curl, int option, ...);

int curl_easy_perform(void *curl);

void curl_easy_cleanup(void *handle);

CTYPE

, "libcurl.so"

);

好了,定义部分就算完成了,现在我们完成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值