Skip to content

FFI: support symbol lookup without specifying lib on Windows #16351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions ext/ffi/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2968,6 +2968,30 @@ static zend_always_inline bool zend_ffi_validate_api_restriction(zend_execute_da
} \
} while (0)

#ifdef PHP_WIN32
# define NUM_MODULES 1024
/* A rough approximation of dlysm(RTLD_DEFAULT) */
static void *dlsym_loaded(char *symbol)
{
HMODULE modules[NUM_MODULES];
DWORD num, i;
void * addr;
if (!EnumProcessModules(GetCurrentProcess(), modules, sizeof modules, &num)) {
return NULL;
}
if (num >= NUM_MODULES) {
num = NUM_MODULES - 1;
}
for (i = 0; i < num; i++) {
addr = GetProcAddress(modules[i], symbol);
if (addr != NULL) break;
}
return addr;
}
# undef DL_FETCH_SYMBOL
# define DL_FETCH_SYMBOL(h, s) (h == NULL ? dlsym_loaded(s) : GetProcAddress(h, s))
#endif

ZEND_METHOD(FFI, cdef) /* {{{ */
{
zend_string *code = NULL;
Expand Down
7 changes: 3 additions & 4 deletions ext/ffi/tests/100.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ FFI 100: PHP symbols
--EXTENSIONS--
ffi
--SKIPIF--
<?php require_once('utils.inc'); ?>
<?php
try {
ffi_cdef("extern void *zend_printf;", ffi_get_php_dll_name());
FFI::cdef("extern void *zend_printf;");
} catch (Throwable $e) {
die('skip PHP symbols not available');
}
Expand All @@ -17,7 +16,7 @@ ffi.enable=1
<?php
require_once('utils.inc');
$fastcall = ffi_get_fastcall_specifier();
$zend = ffi_cdef("
$zend = FFI::cdef("
const char *get_zend_version(void);
//char *get_zend_version(void);
extern size_t (*zend_printf)(const char *format, ...);
Expand All @@ -26,7 +25,7 @@ $zend = ffi_cdef("

void $fastcall zend_str_tolower(char *str, size_t length);

", ffi_get_php_dll_name());
");
var_dump(trim(explode("\n",$zend->get_zend_version())[0]));
//var_dump(trim(FFI::string($zend->get_zend_version())));
var_dump($zend->zend_printf);
Expand Down
7 changes: 3 additions & 4 deletions ext/ffi/tests/101.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ FFI 101: PHP symbols (function address)
--EXTENSIONS--
ffi
--SKIPIF--
<?php require_once('utils.inc'); ?>
<?php
try {
ffi_cdef("extern void *zend_printf;", ffi_get_php_dll_name());
FFI::cdef("extern void *zend_printf;");
} catch (Throwable $e) {
die('skip PHP symbols not available');
}
Expand All @@ -17,7 +16,7 @@ ffi.enable=1
<?php
require_once('utils.inc');
$fastcall = ffi_get_fastcall_specifier();
$zend = ffi_cdef("
$zend = FFI::cdef("
const char *get_zend_version(void);
//char *get_zend_version(void);
extern size_t (*zend_printf)(const char *format, ...);
Expand All @@ -26,7 +25,7 @@ $zend = ffi_cdef("

void $fastcall zend_str_tolower(char *str, size_t length);

", ffi_get_php_dll_name());
");
$f = $zend->get_zend_version;
var_dump(trim(explode("\n",$f())[0]));
//var_dump(trim(FFI::string($zend->get_zend_version())));
Expand Down
4 changes: 2 additions & 2 deletions ext/ffi/tests/200.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ffi
<?php require_once('utils.inc'); ?>
<?php
try {
FFI::cdef("void* zend_write;", ffi_get_php_dll_name());
FFI::cdef("void* zend_write;");
} catch (Throwable $e) {
die('skip PHP symbols not available');
}
Expand All @@ -20,7 +20,7 @@ require_once('utils.inc');
$zend = FFI::cdef("
typedef size_t (*zend_write_func_t)(const char *str, size_t str_length);
extern zend_write_func_t zend_write;
", ffi_get_php_dll_name());
");

echo "Hello World!\n";

Expand Down
4 changes: 0 additions & 4 deletions ext/ffi/tests/300-win32.h.in

This file was deleted.

29 changes: 0 additions & 29 deletions ext/ffi/tests/301-win32.phpt

This file was deleted.

2 changes: 0 additions & 2 deletions ext/ffi/tests/301.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
FFI 301: FFI loading
--EXTENSIONS--
ffi
--SKIPIF--
<?php if (substr(PHP_OS, 0, 3) == 'WIN') die('skip not for Windows'); ?>
--INI--
ffi.enable=1
--FILE--
Expand Down
6 changes: 2 additions & 4 deletions ext/ffi/tests/bug77632b.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ Bug #77632 (FFI function pointers with variadics)
ffi
--SKIPIF--
<?php
require_once('utils.inc');
try {
FFI::cdef("extern void *zend_printf;", ffi_get_php_dll_name());
FFI::cdef("extern void *zend_printf;");
} catch (Throwable $_) {
die('skip PHP symbols not available');
}
Expand All @@ -15,8 +14,7 @@ try {
ffi.enable=1
--FILE--
<?php
require_once('utils.inc');
$libc = FFI::cdef("extern size_t (*zend_printf)(const char *format, ...);", ffi_get_php_dll_name());
$libc = FFI::cdef("extern size_t (*zend_printf)(const char *format, ...);");
$args = ["test from zend_printf\n"];
($libc->zend_printf)(...$args);
$args2 = ["Hello, %s from zend_printf\n", "world"];
Expand Down
3 changes: 1 addition & 2 deletions ext/ffi/tests/bug78714.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ ffi
ffi.enable=1
--FILE--
<?php
require_once('utils.inc');
$def = 'char * __cdecl get_zend_version(void);';
$ffi = ffi_cdef($def, ffi_get_php_dll_name());
$ffi = FFI::cdef($def);
echo substr(FFI::string($ffi->get_zend_version()), 0, 4) . "\n";
?>
--EXPECT--
Expand Down
12 changes: 1 addition & 11 deletions ext/ffi/tests/bug79096.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ ffi
zend_test
--FILE--
<?php
require_once('utils.inc');
$header = <<<HEADER
struct bug79096 {
uint64_t a;
Expand All @@ -15,16 +14,7 @@ struct bug79096 {
struct bug79096 bug79096(void);
HEADER;

if (PHP_OS_FAMILY !== 'Windows') {
$ffi = FFI::cdef($header);
} else {
try {
$ffi = FFI::cdef($header, 'php_zend_test.dll');
} catch (FFI\Exception $ex) {
$ffi = FFI::cdef($header, ffi_get_php_dll_name());
}
}

$ffi = FFI::cdef($header);
$struct = $ffi->bug79096();
var_dump($struct);
?>
Expand Down
12 changes: 1 addition & 11 deletions ext/ffi/tests/bug79177.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,12 @@ ffi
zend_test
--FILE--
<?php
require_once __DIR__ . '/utils.inc';
$header = <<<HEADER
extern int *(*bug79177_cb)(void);
void bug79177(void);
HEADER;

if (PHP_OS_FAMILY !== 'Windows') {
$ffi = FFI::cdef($header);
} else {
try {
$ffi = FFI::cdef($header, 'php_zend_test.dll');
} catch (FFI\Exception $ex) {
$ffi = FFI::cdef($header, ffi_get_php_dll_name());
}
}

$ffi = FFI::cdef($header);
$ffi->bug79177_cb = function() {
throw new \RuntimeException('Not allowed');
};
Expand Down
13 changes: 1 addition & 12 deletions ext/ffi/tests/bug79532.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,11 @@ ffi
zend_test
--FILE--
<?php
require_once('utils.inc');

$header = <<<HEADER
void bug79532(off_t *array, size_t elems);
HEADER;

if (PHP_OS_FAMILY !== 'Windows') {
$ffi = FFI::cdef($header);
} else {
try {
$ffi = FFI::cdef($header, 'php_zend_test.dll');
} catch (FFI\Exception $ex) {
$ffi = FFI::cdef($header, ffi_get_php_dll_name());
}
}

$ffi = FFI::cdef($header);
$array = FFI::cdef()->new("off_t[3]");
$ffi->bug79532($array, 3);
var_dump($array);
Expand Down
11 changes: 1 addition & 10 deletions ext/ffi/tests/bug80847.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ if (PHP_OS_FAMILY == 'Windows' && ((1 << 31) > 0)) die('xfail libffi doesn\'t pr
?>
--FILE--
<?php
require_once('utils.inc');
$header = <<<HEADER
typedef struct bug80847_01 {
uint64_t b;
Expand All @@ -23,15 +22,7 @@ $header = <<<HEADER
bug80847_02 ffi_bug80847(bug80847_02 s);
HEADER;

if (PHP_OS_FAMILY !== 'Windows') {
$ffi = FFI::cdef($header);
} else {
try {
$ffi = FFI::cdef($header, 'php_zend_test.dll');
} catch (FFI\Exception $ex) {
$ffi = FFI::cdef($header, ffi_get_php_dll_name());
}
}
$ffi = FFI::cdef($header);
$x = $ffi->new('bug80847_02');
$x->a->b = 42;
$x->a->c = 42.5;
Expand Down
11 changes: 1 addition & 10 deletions ext/ffi/tests/bug_gh9090.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ zend_test
--FILE--
<?php

require_once 'utils.inc';
$h = <<<'EOD'
void (*bug_gh9090_void_none_ptr)();
void (*bug_gh9090_void_int_char_ptr)(int, char *);
Expand All @@ -19,15 +18,7 @@ void bug_gh9090_void_int_char(int i, char *s);
void bug_gh9090_void_int_char_var(int i, char *fmt, ...);
EOD;

if (PHP_OS_FAMILY !== 'Windows') {
$ffi = FFI::cdef($h);
} else {
try {
$ffi = FFI::cdef($h, 'php_zend_test.dll');
} catch (FFI\Exception $ex) {
$ffi = FFI::cdef($h, ffi_get_php_dll_name());
}
}
$ffi = FFI::cdef($h);

$func_ptrs = [
'bug_gh9090_void_none_ptr',
Expand Down
12 changes: 1 addition & 11 deletions ext/ffi/tests/gh11934b.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,11 @@ ffi
zend_test
--FILE--
<?php
require_once __DIR__ . '/utils.inc';
$header = <<<HEADER
extern int gh11934b_ffi_var_test_cdata;
HEADER;

if (PHP_OS_FAMILY !== 'Windows') {
$ffi = FFI::cdef($header);
} else {
try {
$ffi = FFI::cdef($header, 'php_zend_test.dll');
} catch (FFI\Exception $ex) {
$ffi = FFI::cdef($header, ffi_get_php_dll_name());
}
}

$ffi = FFI::cdef($header);
$ffi->gh11934b_ffi_var_test_cdata->cdata = 2;
var_dump($ffi->gh11934b_ffi_var_test_cdata);
$source = $ffi->new('int');
Expand Down
20 changes: 1 addition & 19 deletions ext/ffi/tests/utils.inc
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
<?php

function ffi_cdef($code, $lib)
{
if (isset($lib)) {
return FFI::cdef($code, $lib);
} else {
return FFI::cdef($code);
}
}

function ffi_get_php_dll_name()
{
if (PHP_OS_FAMILY === 'Windows') {
return "php" . PHP_MAJOR_VERSION . (PHP_ZTS ? "ts" : "") . (PHP_DEBUG ? "_debug" : "") . ".dll";
} else {
return null;
}
}

function ffi_get_fastcall_specifier()
{
foreach (['__attribute__((fastcall))', '__fastcall', '__vectorcall'] as $spec) {
try {
ffi_cdef("extern size_t $spec zend_list_insert(void *ptr, int type);", ffi_get_php_dll_name());
FFI::cdef("extern size_t $spec zend_list_insert(void *ptr, int type);");
return "$spec ";
} catch (Throwable $e) {}
}
Expand Down
Loading