Search code examples
phpffi

Is it possible to pass PHP variable to FFI C function?


I want to explore PHP variables on C level with FFI. Is it possible?
I wrote code, but it doesn't work correctly.

php_ffi.cpp

#include "zend_types.h"
#include "main/php.h"

int main() {}

extern "C" void print_zval_info(zval zv) {
    printf("type: %d\n", Z_TYPE(zv));
}

test.php

<?php

$cpp_ffi = \FFI::cdef(
    "void print_zval_info(zval zv);",
    __DIR__ . "/php_ffi.so");

$a = 1;
$cpp_ffi->print_zval_info($a);

How to reproduce:

git clone [email protected]:php/php-src.git && cd php-src
./buildconf
./configure --enable-debug --with-ffi
g++ -g -fPIC -shared -I . -I Zend -I main -I TSRM php_ffi.cpp -o php_ffi.so
php test.php

Solution

  • You can't pass PHP variable to FFI C function, but you can access that variable in C code:

    library.cpp

    #include "main/php.h"
    #include "zend_types.h"
    #include "zend_string.h"
    
    extern "C" void test_var(char *name) {
    
        HashTable *symbol_table = zend_array_dup(zend_rebuild_symbol_table());
    
        zend_string *key_name = zend_string_init(name, strlen(name), 0);
        zval *data = zend_hash_find(symbol_table, key_name);
    
        if(data != NULL) {
          //do something with data
        }
      
        zend_string_release(key_name);
        zend_array_destroy(symbol_table);
    }
    

    compile library.cpp to library.so

    g++ -O3 -fPIC -shared -o library.so library.cpp
    

    test.php

    <?php
    
    function test_var($myLocalVariable) {
        $libc = \FFI::cdef("void test_var(char *name);","library.so");
        $libc->test_var('myLocalVariable');
    }
    
    
    $var = 1;
    test_var($var);
    

    You can see the complete example in this library