Home  >  Article  >  Backend Development  >  Allow PHP to call C functions: FFI extension (with code)

Allow PHP to call C functions: FFI extension (with code)

醉折花枝作酒筹
醉折花枝作酒筹forward
2021-06-09 17:09:441985browse

This article will introduce to you the functions that allow PHP to call C: FFI extension. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.

Allow PHP to call C functions: FFI extension (with code)

#In large companies, there are usually many programming languages. For example, let Java be used as the microservice layer, C be used for underlying operations, PHP be used as the middle layer, and finally JS can be used to display the effect. Most of the cooperation between these languages ​​is completed through RPC, or the data is directly stored in the database and then retrieved using different languages. So, can our PHP code directly call these languages? In fact, PHP has really prepared an extension library for us that can directly call the C language, and this extension library is already built into PHP by default. It is the FFI extension.

What is FFI

FFI, ​​Foreign Function Interface, external function interface. This extension allows us to load some public libraries (.dll, .so), which actually means that we can call some C data structures and functions. It is already an extension released with the PHP source code. You can add --with-ffi when compiling to compile it directly into the PHP program.

We already have compiled PHP here, so we find this extension directly and perform simple extension installation steps to complete the installation.

cd php-7.4.4/ext/ffi/
phpize
./configure
make && make install

After the installation is complete, remember to open the extension in the php.ini file. One thing to note about this extension is that it has a configuration item ffi.enable. By default, the value of this configuration item is "preload", which only enables FFI capabilities in the CLI SAPI environment. Of course, we can also change it to "true" or "false" to turn it on and off. Setting to "true" will enable this extension in all environments.

Use FFI to call C functions

Next, let’s take a brief look at how it calls C functions.

// 创建一个 FFI 对象,加载 libc 并且导入 printf 函数
$ffi_printf = FFI::cdef(
    "int printf(const char *format, ...);", // C 的定义规则
    "libc.so.6"); // 指定 libc 库
// 调用 C 的 printf 函数
$ffi_printf->printf("Hello %s!\n", "world"); // Hello World

// 加载 math 并且导入 pow 函数
$ffi_pow = FFI::cdef(
    "double pow(double x, double y);", 
    "libboost_math_c99.so.1.66.0");
// 这里调用的是 C 的 pow 函数,不是 PHP 自己的
echo $ffi_pow->pow(2,3), PHP_EOL; // 8

We created two objects and called C’s printf() and pow() functions respectively. FFI::cdef() is used to create an FFI object. It receives two parameters, one is a string containing the declaration sequence of regular C language (type, structure, function, variable, etc.).

Actually, this string can be copied and pasted from the C header file. The other parameter is the name of the shared library file to be loaded and linked. That is, the .dll or .so file we need, which corresponds to the string we declare. For example, there is no calculation function such as pow() in libc.so.6, so we have to find the math-related C Language calculation function library.

Define variables and arrays

Of course, FFI can also define variables and arrays.

// 创建一个 int 变量
$x = FFI::new("int");
var_dump($x->cdata); // int(0)

// 为变量赋值
$x->cdata = 5;
var_dump($x->cdata); // int(5)

// 计算变量
$x->cdata += 2;
var_dump($x->cdata); // int(7)


// 结合上面的两个 FFI 对象操作

echo "pow value:", $ffi_pow->pow($x->cdata, 3), PHP_EOL;
// pow value:343
$ffi_printf->printf("Int Pow value is : %f\n", $ffi_pow->pow($x->cdata, 3));
// Int Pow value is : 343.000000


// 创建一个数组
$a = FFI::new("long[1024]");
// 为数组赋值
for ($i = 0; $i < count($a); $i++) {
    $a[$i] = $i;
}
var_dump($a[25]); // int(25)

$sum = 0;
foreach ($a as $n) {
    $sum += $n;
}
var_dump($sum); // int(523776)

var_dump(count($a)); // int(1024) 数组长度
var_dump(FFI::sizeof($a)); // int(8192),内存大小

Use the FFI::new() function to create a C data structure, that is, variable declaration. The contents of these variables will be saved in the cdata attribute. The array can directly operate on the return value of this function. Of course, when we want to end use, we still need to use FFI::free() to release the variables, just like C language development.

Summary

Doesn’t it feel very high-end? But please note that the C functions called by FFI are not as efficient as those called by PHP itself. For example, using the pow() function is more efficient using PHP itself. Moreover, although the FFI extension has been released simultaneously with PHP, it is still experimental. In other words, this extension is prepared for other functions that may be used in the future, and there are still many uncertainties. Therefore, if you need similar functions in a production environment, you still need to do more in-depth research.

Test code:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202004/source/%E8%AE%A9PHP%E8%83%BD%E5%A4%9F%E8%B0%83%E7%94%A8C%E7%9A%84%E5%87%BD%E6%95%B0-FFI%E6%89%A9%E5%B1%95.php

Recommended learning: php video tutorial

The above is the detailed content of Allow PHP to call C functions: FFI extension (with code). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete