>  기사  >  백엔드 개발  >  PHP가 C 함수를 호출하도록 허용: FFI 확장(코드 포함)

PHP가 C 함수를 호출하도록 허용: FFI 확장(코드 포함)

醉折花枝作酒筹
醉折花枝作酒筹앞으로
2021-06-09 17:09:442059검색

이 글에서는 PHP가 C: FFI 확장을 호출할 수 있는 기능을 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.

PHP가 C 함수를 호출하도록 허용: FFI 확장(코드 포함)

대기업에는 대개 프로그래밍 언어가 많습니다. 예를 들어, Java를 마이크로서비스 계층으로 사용하고, C++를 사용하여 기본 작업을 수행하고, PHP를 중간 계층으로 사용하고, 마지막으로 JS를 사용하여 효과를 표시하도록 합니다. 이러한 언어 간의 협력은 대부분 RPC를 통해 완료되거나 데이터가 데이터베이스에 직접 저장된 후 다른 언어를 사용하여 검색됩니다. 그렇다면 PHP 코드가 이러한 언어를 직접 호출할 수 있습니까? 실제로 PHP는 실제로 C 언어를 직접 호출할 수 있는 확장 라이브러리를 준비했는데, 이 확장 라이브러리는 이미 기본적으로 PHP에 내장되어 있습니다.

FFI란 무엇입니까

FFI, 외국 함수 인터페이스, 외국 함수 인터페이스. 이 확장을 사용하면 일부 공용 라이브러리(.dll, .so)를 로드할 수 있으며 이는 실제로 일부 C 데이터 구조 및 함수를 호출할 수 있음을 의미합니다. 이는 이미 PHP 소스 코드와 함께 출시된 확장입니다. 컴파일할 때 --with-ffi를 추가하여 PHP 프로그램으로 직접 컴파일할 수 있습니다.

여기에는 이미 PHP가 컴파일되어 있으므로 이 확장을 직접 찾아 간단한 확장 설치 단계를 수행하여 설치를 완료합니다.

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

설치 후 php.ini 파일에서 확장 프로그램을 여는 것을 잊지 마세요. 이 확장에 대해 주목해야 할 점은 구성 항목 ffi.enable이 있다는 것입니다. 기본적으로 이 구성 항목의 값은 CLI SAPI 환경에서 FFI 기능만 활성화하는 "preload"입니다. 물론 "true" 또는 "false"로 변경하여 켜거나 끌 수도 있습니다. "true"로 설정하면 모든 환경에서 이 확장이 활성화됩니다.

FFI를 사용하여 C 함수 호출

다음으로 C 함수 호출 방법을 간략하게 살펴보겠습니다.

// 创建一个 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

우리는 두 개의 객체를 생성하고 C의 printf() 및 pow() 함수를 각각 호출했습니다. FFI::cdef()는 FFI 객체를 생성하는 데 사용됩니다. 이는 두 개의 매개변수를 받습니다. 하나는 일반 C 언어의 선언 시퀀스(유형, 구조, 함수, 변수 등)가 포함된 문자열입니다.

실제로 이 문자열은 C 헤더 파일에서 복사하여 붙여넣을 수 있습니다. 다른 매개변수는 로드하고 링크할 공유 라이브러리 파일의 이름입니다. 그것이 우리가 선언한 문자열에 해당하는 .dll 또는 .so 파일입니다. 예를 들어 libc.so.6에는 pow()와 같은 계산 함수가 없으므로 수학 관련 C를 찾아야 합니다. 언어 계산 기능 라이브러리.

변수 및 배열 정의

물론 FFI에서는 변수와 배열도 정의할 수 있습니다.

// 创建一个 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),内存大小

FFI::new() 함수를 사용하여 C 데이터 구조, 즉 변수 선언을 생성하면 이러한 변수의 내용이 cdata 속성에 저장됩니다. 배열은 이 함수의 반환 값에 대해 직접 작동할 수 있습니다. 물론 사용을 종료하려면 C 언어 개발과 마찬가지로 FFI::free()를 사용하여 변수를 해제해야 합니다.

요약

정말 숭고한 느낌이 들지 않나요? 그러나 FFI에서 호출하는 C 함수는 PHP 자체에서 호출하는 C 함수만큼 효율적이지 않습니다. 예를 들어, 이 pow() 함수를 사용하면 PHP 자체를 사용하는 것이 더 효율적입니다. 또한 FFI 확장은 PHP와 동시에 출시되었지만 아직 실험적입니다. 즉, 이번 확장은 향후 사용될 수 있는 다른 기능에 대비해 준비한 것으로 아직 불확실성이 많다. 따라서 프로덕션 환경에서 유사한 기능이 필요하다면 여전히 더 심층적인 조사가 필요합니다.

테스트 코드:

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

추천 학습: php 비디오 튜토리얼

위 내용은 PHP가 C 함수를 호출하도록 허용: FFI 확장(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제