PHP의 FFI (외부 기능 인터페이스) 확장을 통해 PHP에서 직접 C 언어 기능 및 데이터 구조를 호출 할 수 있으며, 이는 성능에 민감하거나 기본 상호 작용 시나리오를 처리하는 데 매우 유용합니다. 그러나 일단 심도있게 사용하면 ffi :: cdef () 에서 구조물을 선언 할 때 구조물을 쓰는 것을 잊어 버리면 숨겨진 "광산"을 찾을 수 있습니다.
간단한 C 구조가 있다고 가정합니다.
typedef struct {
int x;
int y;
} Point;
PHP의 ffi :: cdef () 선언을 사용합니다.
$ffi = FFI::cdef("
typedef struct {
int x;
int y;
} Point;
");
그런 다음 다음과 같이 사용할 수 있습니다.
$point = $ffi->new("Point");
$point->x = 10;
$point->y = 20;
echo "Point: ({$point->x}, {$point->y})\n";
모든 것이 정상적으로 실행 중입니다. 그러나 이제 문제는 다음과 같습니다. 구조물을 쓰는 것을 잊어 버리면 어떻게됩니까?
C 언어에서 구조 지점 과 포인트는 두 가지 다른 네임 스페이스입니다. typedef를 사용하지 않는 한 Point는 유효한 유형 이름이 아닙니다. PHP의 ffi :: cdef () 에서 상황은 약간 다릅니다. 구문 분석 규칙은 C 컴파일러와 약간 다르며 결함 공차는 낮습니다.
예를 들어, 당신은 다음과 같은 진술을 썼습니다.
$ffi = FFI::cdef("
typedef struct Point {
int x;
int y;
} Point;
");
$pt = $ffi->new("Point");
이 코드는 괜찮습니다. 그러나 당신이 부주의하게 typedef 부분을 놓치면 예를 들어.
$ffi = FFI::cdef("
struct Point {
int x;
int y;
};
");
$pt = $ffi->new("Point"); // 오류가 발생했습니다
여기서 $ ffi-> new ( "Point")는 "포인트"유형을 찾을 수 없다는 것을 알리면서 예외를 던질 것입니다. 현재 "포인트"는 별도의 유형 별명이 아닌 구조 지점 이기 때문입니다.
올바른 호출은 다음과 같습니다.
$pt = $ffi->new("struct Point");
이것은 많은 사람들이 들어가는 함정입니다. 그들은 구조 이름 "포인트"를 정의했다고 생각하지만 실제로는 "구조 지점"만 정의합니다. typedef를하지 않으면 직접 포인트를 사용할 수 없습니다.
다음과 같은 오류가 표시되는 경우 :
FFI\Exception: undefined C type 'Point'
그런 다음 먼저 cdef () 에서 어떻게 선언하는지 확인해야합니다. typedef없이 구조물 지점을 작성 했습니까? 그렇다면 struct point를 사용하여 참조 할 수 있습니다.
디버깅 기술은 CDEF () 선언을 인쇄하여 구조에 입력한지 여부를 확인하는 것입니다.
echo $ffi->cdef;
이 방법이 항상 작동하지는 않지만 (특히 일부 버전의 PHP에서) 유형이 올바르게 등록되었는지 확인하는 데 도움이 될 수 있습니다.
혼란을 피하기 위해 모든 구조적 선언에서 TypEdef를 가져 오는 것이 좋습니다. 예를 들어:
typedef struct {
int x;
int y;
} Point;
이런 식으로, 당신은 PHP에 $ ffi-> new ( "Point")를 행복하게 쓸 수 있으며 더 이상 Struct Prefix를 추가할지 걱정할 필요가 없습니다.
다른 구조를 중첩하는 구조를 정의한다고 가정 해 봅시다.
typedef struct {
int x;
int y;
} Point;
typedef struct {
Point start;
Point end;
} Line;
PHP의 ffi :: cdef () 는 다음과 같이 작성해야합니다.
$ffi = FFI::cdef("
typedef struct {
int x;
int y;
} Point;
typedef struct {
Point start;
Point end;
} Line;
");
그런 다음 다음과 같이 사용할 수 있습니다.
$line = $ffi->new("Line");
$line->start->x = 1;
$line->start->y = 2;
$line->end->x = 10;
$line->end->y = 20;
echo "Start: ({$line->start->x}, {$line->start->y})\n";
echo "End: ({$line->end->x}, {$line->end->y})\n";
Point 와 같은 선언에서 TypEdef를 놓친 경우 Point에 TypEdef가 없으면 선의 정의가 포인트 유형을 찾을 수 없으므로 오류를보고합니다.
PHP FFI를 사용하여 C의 구조를 호출 할 때는 다음 사항에주의를 기울여야합니다.
구조가 typedef가 아닌 경우 유형 이름은 struct 와 접두사를해야합니다.
모든 구조물은 이름 지정 혼란을 피하기 위해 TypEdef 선언을 사용하는 것이 좋습니다.
디버깅 할 때 정의되지 않은 유형 오류가 발생했습니다. 먼저 CDEF의 선언이 일관된 지 확인하십시오.
이러한 사양을 통해 설명 할 수없는 유형 오류가 많이 줄어서 PHP와 함께 C 인터페이스를 할 때 함정을 줄이고 머리카락을 잃을 수 있습니다.
PHP FFI에 대한 자세한 예는 https://gitbox.net/docs/php-ffi-examples 를 참조하십시오.