Bug #79144 [Nab]: FFI call exported function without referencing it

From: Date: Mon, 20 Jan 2020 22:53:29 +0000
Subject: Bug #79144 [Nab]: FFI call exported function without referencing it
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-225021@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79144&edit=1 ID: 79144 Updated by: requinix@php.net Reported by: php at tim dot ainfach dot de Summary: FFI call exported function without referencing it Status: Not a bug Type: Bug Package: *Extensibility Functions Operating System: OSX 10.14.6 PHP Version: 7.4.1 Block user comment: N Private report: N New Comment: In other other ticket, > struct bug79096 bug79096(void); bug79096 is defined as a function. In this ticket, > extern zend_write_func_t zend_write; zend_write is defined as a variable. Because it actually is a variable. Zend Engine stuff. If you want to call "the zend_write function" you have to find out what the actual underlying function is. I'll spare you the legwork and tell you that (normally) it is php_output_write, implemented in main/output.c. So $zend = FFI::cdef(" int php_output_write(const char *str, size_t str_length); "); $zend->php_output_write("aaa", 3); Of course, doing it this way doesn't get you the actual zend_write "function". It gets you php_output_write. But maybe that's fine for you. Previous Comments: ------------------------------------------------------------------------ [2020-01-20 22:02:33] php at tim dot ainfach dot de thank you for the explanation. it feels very inconsitent because for example if i export a function from C like here https://bugs.php.net/bug.php?id=79125 i am able fo call $ffi->FUNCTION() directly. there is a reason why different approaches were chosen here? ------------------------------------------------------------------------ [2020-01-20 21:53:53] requinix@php.net $zend->zend_write is a property, not a method. It's as if you wrote $zend = new stdClass(); $zend->zend_write = function(string $str, int $str_length) { ... }; ------------------------------------------------------------------------ [2020-01-20 21:27:50] php at tim dot ainfach dot de Description: ------------ when using a function that is exported by php (ZEND_API) it's not possible to call the function directly. You've to create a reference to the function and then it is possible to call it. i would expect that it is possible to call the function directly. these are working fine: $a = $zend->zend_write; $a("aaa", 3); ($zend->zend_write)("aaa", 3); (clone $zend->zend_write)("aaa", 3); this doesn't work -> Attempt to call undefined C function 'zend_write' $zend->zend_write("aaa", 3); $a = [$zend, 'zend_write']; $a("aaa", 3); Test script: --------------- public static function assertObSame(string $expected, callable $cb) { ob_start(); $cb(); $res = ob_get_contents(); ob_end_clean(); static::assertSame($expected, $res); } public function testReturnU64() { $zend = FFI::cdef(" typedef int (*zend_write_func_t)(const char *str, size_t str_length); extern zend_write_func_t zend_write; "); static::assertObSame('aaa', function() use ($zend) { $a = $zend->zend_write; $a("aaa", 3); }); static::assertObSame('aaa', function() use ($zend) { ($zend->zend_write)("aaa", 3); }); static::assertObSame('aaa', function() use ($zend) { (clone $zend->zend_write)("aaa", 3); }); // does not work -> end up in a Attempt to call undefined C function 'zend_write' static::assertObSame('aaa', function() use ($zend) { $zend->zend_write("aaa", 3); }); static::assertObSame('aaa', function() use ($zend) { $a = [$zend, 'zend_write']; $a("aaa", 3); }); } Expected result: ---------------- all ways to call zend_write should give the same result (pass the assertion). Actual result: -------------- FFI\Exception: Attempt to call undefined C function 'zend_write' ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=79144&edit=1

« previous php.bugs (#225021) next »