Current Location: Home> Latest Articles> What happens if you forget to define struct in FFI::cdef?

What happens if you forget to define struct in FFI::cdef?

gitbox 2025-05-28

PHP's FFI (Foreign Function Interface) extension allows us to call C language functions and data structures directly in PHP, which is very useful in handling performance-sensitive or underlying interaction scenarios. But once you use it in depth, you will find some hidden "mines", such as - what happens if you forget to write struct when declaring a struct in FFI::cdef() ?

Let's take a look at a basic example

Suppose we have a simple C structure:

 typedef struct {
    int x;
    int y;
} Point;

We use PHP's FFI::cdef() declaration:

 $ffi = FFI::cdef("
    typedef struct {
        int x;
        int y;
    } Point;
");

Then you can use it like this:

 $point = $ffi->new("Point");
$point->x = 10;
$point->y = 20;
echo "Point: ({$point->x}, {$point->y})\n";

Everything is running normally. But now the question is: What happens if you forget to write struct ?

The trap of forgetting to write struct

In C language, struct Point and Point are two different namespaces. Unless you use typedef , Point is not a valid type name. In PHP's FFI::cdef() , the situation is slightly different - its parsing rules are slightly different from those of the C compiler, and the fault tolerance is low.

For example, you wrote a statement like this:

 $ffi = FFI::cdef("
    typedef struct Point {
        int x;
        int y;
    } Point;
");

$pt = $ffi->new("Point");

This code is OK. But if you carelessly miss the typedef part, for example:

 $ffi = FFI::cdef("
    struct Point {
        int x;
        int y;
    };
");

$pt = $ffi->new("Point"); // An error occurred

Here $ffi->new("Point") will throw an exception, prompting that the type "Point" cannot be found. Because at this time "Point" is a struct Point , not a separate type alias.

The correct call should be:

 $pt = $ffi->new("struct Point");

This is the pitfall that many people fall into: they think that they have defined the structure name "Point", but in fact, you only define "struct Point". If you don't do typedef, you cannot use Point directly.

How to troubleshoot this problem?

If you see an error like the following:

 FFI\Exception: undefined C type 'Point'

Then you first need to check how you declare it in cdef() . Did you just write struct Point without typedef? If so, you can only use struct Point to reference.

A debugging technique is to print out your cdef() declaration to check whether the structure has typedef, for example:

 echo $ffi->cdef;

Although this method does not always work (especially in some versions of PHP), it can help you confirm that the type is registered correctly.

Suggested practice: All typesedef

To avoid confusion, it is recommended that you bring typedef in all structural declarations. For example:

 typedef struct {
    int x;
    int y;
} Point;

In this way, you can happily write $ffi->new("Point") in PHP, and no longer have to worry about whether to add struct prefix.

To give a more complex example: structure nesting

Suppose you define a structure that nests another structure:

 typedef struct {
    int x;
    int y;
} Point;

typedef struct {
    Point start;
    Point end;
} Line;

FFI::cdef() in PHP should be written like this:

 $ffi = FFI::cdef("
    typedef struct {
        int x;
        int y;
    } Point;

    typedef struct {
        Point start;
        Point end;
    } Line;
");

Then you can use it like this:

 $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";

If you miss typedef in the declaration, such as Point does not have typedef, then the definition of Line will report an error because it cannot find the Point type.

summary

When calling C's structure using PHP FFI, be sure to pay attention to the following points:

  1. If the structure is not typedef, the type name must be prefixed with struct

  2. It is recommended that all structures use typedef declarations to avoid naming confusion

  3. When debugging, I encountered an undefined type error. First check whether the declarations in cdef are consistent.

Through these specifications, you can reduce a lot of inexplicable type errors, allowing you to reduce pitfalls and lose hair when playing C interface with PHP.

For more examples about PHP FFI, please refer to https://gitbox.net/docs/php-ffi-examples .