현재 위치: > 최신 기사 목록> ffi :: cdef에서 struct를 정의하는 것을 잊어 버리면 어떻게됩니까?

ffi :: cdef에서 struct를 정의하는 것을 잊어 버리면 어떻게됩니까?

gitbox 2025-05-28

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의 구조를 호출 할 때는 다음 사항에주의를 기울여야합니다.

  1. 구조가 typedef가 아닌 경우 유형 이름은 struct 와 접두사를해야합니다.

  2. 모든 구조물은 이름 지정 혼란을 피하기 위해 TypEdef 선언을 사용하는 것이 좋습니다.

  3. 디버깅 할 때 정의되지 않은 유형 오류가 발생했습니다. 먼저 CDEF의 선언이 일관된 지 확인하십시오.

이러한 사양을 통해 설명 할 수없는 유형 오류가 많이 줄어서 PHP와 함께 C 인터페이스를 할 때 함정을 줄이고 머리카락을 잃을 수 있습니다.

PHP FFI에 대한 자세한 예는 https://gitbox.net/docs/php-ffi-examples 를 참조하십시오.