Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
chopins committed Oct 2, 2020
1 parent f400739 commit c09db87
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 81 deletions.
104 changes: 42 additions & 62 deletions src/FFIExtend.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ class FFIExtend
private static $ffi = null;
private static $cffi = null;
private static bool $HAVE_LONG_DOUBLE = false;
private static array $ZEND_FFI_TYPE_KIND = [];

const ZEND_FFI_SYM_TYPE = 0;
const ZEND_FFI_SYM_VAR = 2;
const ZEND_FFI_SYM_FUNC = 3;
const ZEND_FFI_TYPE_OWNED = 1 << 0;
const ZEND_FFI_ATTR_VARIADIC = 1 << 2;
const ZEND_FFI_ATTR_INCOMPLETE_ARRAY = 1 << 3;
Expand Down Expand Up @@ -95,12 +91,6 @@ public function getffi()
{
return self::$ffi;
}

protected function ZEND_FFI_TYPE_KIND($name)
{
return array_search("ZEND_FFI_TYPE_$name", self::$ZEND_FFI_TYPE_KIND);
}

protected function versionMacro()
{
if (PHP_MAJOR_VERSION < 8) {
Expand All @@ -109,11 +99,17 @@ protected function versionMacro()
self::$IS_ALIAS_PTR = 15;
self::$_IS_NUMBER = 20;
}
$this->ffiTypeArray();
}

protected function ffiTypeArray()
{
public function replaceMacro($name, $check, $value, &$code) {
if($check) {
$code = str_replace($name, $value, $code);
} else {
$code = str_replace($name, '', $code);
}
}

public function haveLongDouble() {
try {
if (FFI::sizeof(FFI::type('long double')) > 8) {
self::$HAVE_LONG_DOUBLE = true;
Expand All @@ -123,31 +119,7 @@ protected function ffiTypeArray()
} catch (FFI\ParserException $e) {
self::$HAVE_LONG_DOUBLE = false;
}
self::$ZEND_FFI_TYPE_KIND = [
'ZEND_FFI_TYPE_VOID',
'ZEND_FFI_TYPE_FLOAT',
'ZEND_FFI_TYPE_DOUBLE'
];
if (self::$HAVE_LONG_DOUBLE) {
self::$ZEND_FFI_TYPE_KIND[] = 'ZEND_FFI_TYPE_LONGDOUBLE';
}
self::$ZEND_FFI_TYPE_KIND = array_merge(self::$ZEND_FFI_TYPE_KIND, [
'ZEND_FFI_TYPE_UINT8',
'ZEND_FFI_TYPE_SINT8',
'ZEND_FFI_TYPE_UINT16',
'ZEND_FFI_TYPE_SINT16',
'ZEND_FFI_TYPE_UINT32',
'ZEND_FFI_TYPE_SINT32',
'ZEND_FFI_TYPE_UINT64',
'ZEND_FFI_TYPE_SINT64',
'ZEND_FFI_TYPE_ENUM',
'ZEND_FFI_TYPE_BOOL',
'ZEND_FFI_TYPE_CHAR',
'ZEND_FFI_TYPE_POINTER',
'ZEND_FFI_TYPE_FUNC',
'ZEND_FFI_TYPE_ARRAY',
'ZEND_FFI_TYPE_STRUCT',
]);
return self::$HAVE_LONG_DOUBLE;
}

private function initPhpApi()
Expand All @@ -159,13 +131,16 @@ private function initPhpApi()
if(defined('PHP_FFI_EXTEND_APPEND_CDEF')) {
$code .= PHP_FFI_EXTEND_APPEND_CDEF;
}
$this->haveLongDouble();

$this->replaceMacro('HAVE_LONG_DOUBLE_ZEND_FFI_TYPE_LONGDOUBLE', self::$HAVE_LONG_DOUBLE, 'ZEND_FFI_TYPE_LONGDOUBLE', $code);

if (strcasecmp(PHP_OS_FAMILY, 'Windows') === 0) {
$code = str_replace('ZEND_FASTCALL', '__vectorcall', $code);
$this->replaceMacro('ZEND_FASTCALL', 1, '__vectorcall', $code);
$phpDll = $this->findPhpDll();
self::$ffi = FFI::cdef($code, $phpDll);
} else {
$code = str_replace('ZEND_FASTCALL', '__attribute__((fastcall))', $code);
$this->replaceMacro('ZEND_FASTCALL', 1, '__attribute__((fastcall))', $code);
if (PHP_DLL_FILE_PATH) {
self::$ffi = FFI::cdef($code, PHP_DLL_FILE_PATH);
} else {
Expand Down Expand Up @@ -325,40 +300,40 @@ protected function getCTypeCDataName(FFI\CData $type)
$name = '';
while (1) {
switch ($type[0]->kind) {
case $this->ZEND_FFI_TYPE_KIND('VOID'):
case self::$ffi->ZEND_FFI_TYPE_VOID:
$name = 'void';
break;
case $this->ZEND_FFI_TYPE_KIND('FLOAT'):
case self::$ffi->ZEND_FFI_TYPE_FLOAT:
$name = 'float';
break;
case $this->ZEND_FFI_TYPE_KIND('DOUBLE'):
case self::$ffi->ZEND_FFI_TYPE_DOUBLE:
$name = 'double';
break;
case $this->ZEND_FFI_TYPE_KIND('UINT8'):
case self::$ffi->ZEND_FFI_TYPE_UINT8:
$name = 'uint8_t';
break;
case $this->ZEND_FFI_TYPE_KIND('SINT8'):
case self::$ffi->ZEND_FFI_TYPE_SINT8:
$name = 'int8_t';
break;
case $this->ZEND_FFI_TYPE_KIND('UINT16'):
case self::$ffi->ZEND_FFI_TYPE_UINT16:
$name = 'uint16_t';
break;
case $this->ZEND_FFI_TYPE_KIND('SINT16'):
case self::$ffi->ZEND_FFI_TYPE_SINT16:
$name = 'int16_t';
break;
case $this->ZEND_FFI_TYPE_KIND('UINT32'):
case self::$ffi->ZEND_FFI_TYPE_UINT32:
$name = 'uint32_t';
break;
case $this->ZEND_FFI_TYPE_KIND('SINT32'):
case self::$ffi->ZEND_FFI_TYPE_SINT32:
$name = 'int32_t';
break;
case $this->ZEND_FFI_TYPE_KIND('UINT64'):
case self::$ffi->ZEND_FFI_TYPE_UINT64:
$name = 'uint64_t';
break;
case $this->ZEND_FFI_TYPE_KIND('SINT64'):
case self::$ffi->ZEND_FFI_TYPE_SINT64:
$name = 'int64_t';
break;
case $this->ZEND_FFI_TYPE_KIND('ENUM'):
case self::$ffi->ZEND_FFI_TYPE_ENUM:
if (!$this->isNull($type[0]->enumeration->tag_name)) {
$tagname = $type[0]->enumeration->tag_name;
$buf = $this->getZStr($tagname) . $buf;
Expand All @@ -367,26 +342,26 @@ protected function getCTypeCDataName(FFI\CData $type)
}
$name = 'enum ';
break;
case $this->ZEND_FFI_TYPE_KIND('BOOL'):
case self::$ffi->ZEND_FFI_TYPE_BOOL:
$name = 'bool';
break;
case $this->ZEND_FFI_TYPE_KIND('CHAR'):
case self::$ffi->ZEND_FFI_TYPE_CHAR:
$name = 'char';
break;
case $this->ZEND_FFI_TYPE_KIND('POINTER'):
case self::$ffi->ZEND_FFI_TYPE_POINTER:
$buf = '*' . $buf;
$is_ptr = 1;
$type = $this->ZEND_FFI_TYPE($type[0]->pointer->type);
break;
case $this->ZEND_FFI_TYPE_KIND('FUNC'):
case self::$ffi->ZEND_FFI_TYPE_FUNC:
if ($is_ptr) {
$is_ptr = 0;
$buf = '(' . $buf . ')';
}
$buf .= '()';
$type = $this->ZEND_FFI_TYPE($type[0]->func[0]->ret_type);
break;
case $this->ZEND_FFI_TYPE_KIND('ARRAY'):
case self::$ffi->ZEND_FFI_TYPE_ARRAY:
if ($is_ptr) {
$is_ptr = 0;
$buf = "($buf)";
Expand All @@ -400,7 +375,7 @@ protected function getCTypeCDataName(FFI\CData $type)
$buf .= ']';
$type = $this->ZEND_FFI_TYPE($type[0]->array->type);
break;
case $this->ZEND_FFI_TYPE_KIND('STRUCT'):
case self::$ffi->ZEND_FFI_TYPE_STRUCT:
if ($type[0]->attr & self::ZEND_FFI_ATTR_UNION) {
if (!$this->isNull($type[0]->record->tag_name)) {
$tagname = $type[0]->record->tag_name;
Expand All @@ -420,7 +395,7 @@ protected function getCTypeCDataName(FFI\CData $type)
}
break;
default:
if (self::$HAVE_LONG_DOUBLE && $type[0]->kind == $this->ZEND_FFI_TYPE_KIND('LONGDOUBLE')) {
if (self::$HAVE_LONG_DOUBLE && $type[0]->kind == self::$ffi->ZEND_FFI_TYPE_LONGDOUBLE) {
$name = 'long double';
break;
}
Expand Down Expand Up @@ -500,19 +475,24 @@ protected function findSymobl(FFI $ffi, string $symName, $symType)

public function hasCFunc(FFI $ffi, string $name)
{
$sym = $this->findSymobl($ffi, $name, self::ZEND_FFI_SYM_FUNC);
$sym = $this->findSymobl($ffi, $name, self::$ffi->ZEND_FFI_SYM_FUNC);
return !$this->isNull($sym);
}

public function hasCVariable(FFI $ffi, string $name)
{
$sym = $this->findSymobl($ffi, $name, self::ZEND_FFI_SYM_VAR);
$sym = $this->findSymobl($ffi, $name, self::$ffi->ZEND_FFI_SYM_VAR);
return !$this->isNull($sym);
}

public function hasCEnum(FFI $ffi, string $name) {
$sym = $this->findSymobl($ffi, $name, self::$ffi->ZEND_FFI_SYM_CONST);
return !$this->isNull($sym);
}

public function hasCType(FFI $ffi, string $type)
{
$sym = $this->findSymobl($ffi, $type, self::ZEND_FFI_SYM_TYPE);
$sym = $this->findSymobl($ffi, $type, self::$ffi->ZEND_FFI_SYM_TYPE);
return !$this->isNull($sym);
}

Expand Down
2 changes: 1 addition & 1 deletion src/ReflectionCFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function __construct(FFI $ffi, $name)
$this->ffi = $ffi;
$this->name = $name;
self::$preName = $name;
$sym = $this->findSymobl($ffi, $name, self::ZEND_FFI_SYM_FUNC);
$sym = $this->findSymobl($ffi, $name, $this->getffi()->ZEND_FFI_SYM_FUNC);
if(!$this->isNull($sym)) {
$this->type = $this->ZEND_FFI_TYPE($sym[0]->type)[0];
return;
Expand Down
23 changes: 23 additions & 0 deletions src/php.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,29 @@ typedef enum _zend_ffi_symbol_kind {
ZEND_FFI_SYM_FUNC
} zend_ffi_symbol_kind;

typedef enum _zend_ffi_type_kind {
ZEND_FFI_TYPE_VOID,
ZEND_FFI_TYPE_FLOAT,
ZEND_FFI_TYPE_DOUBLE,
HAVE_LONG_DOUBLE_ZEND_FFI_TYPE_LONGDOUBLE,
ZEND_FFI_TYPE_UINT8,
ZEND_FFI_TYPE_SINT8,
ZEND_FFI_TYPE_UINT16,
ZEND_FFI_TYPE_SINT16,
ZEND_FFI_TYPE_UINT32,
ZEND_FFI_TYPE_SINT32,
ZEND_FFI_TYPE_UINT64,
ZEND_FFI_TYPE_SINT64,
ZEND_FFI_TYPE_ENUM,
ZEND_FFI_TYPE_BOOL,
ZEND_FFI_TYPE_CHAR,
ZEND_FFI_TYPE_POINTER,
ZEND_FFI_TYPE_FUNC,
ZEND_FFI_TYPE_ARRAY,
ZEND_FFI_TYPE_STRUCT,
} zend_ffi_type_kind;


struct _zend_ffi_type {
int kind;
size_t size;
Expand Down
45 changes: 27 additions & 18 deletions tests/funcArg.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,46 @@
int tz_dsttime;
};
int errno;
typedef enum _zend_ffi_symbol_kind {
ZEND_FFI_SYM_TYPE,
ZEND_FFI_SYM_CONST,
ZEND_FFI_SYM_VAR,
ZEND_FFI_SYM_FUNC
} zend_ffi_symbol_kind;
int gettimeofday(struct timeval *tv, struct timezone *tz); ", "libc.so.6");

$c = new FFIExtend;
$r = $c->hasCFunc($ffi, 'printf');
var_dump('==== has printf():', $r);

var_dump('has printf():', $r);
echo '**********************' .PHP_EOL;
$r = $c->hasCFunc($ffi, 'printfs');
var_dump('==== has printfs():', $r);

var_dump('has printfs():', $r);
echo '**********************' .PHP_EOL;
$r = $c->hasCFunc($ffi, 'gettimeofday');
var_dump('==== has gettimeofday():', $r);

var_dump('has gettimeofday():', $r);
echo '**********************' .PHP_EOL;
$var = $c->hasCVariable($ffi, 'errno');
var_dump('=== has variable `errno`:', $var);

var_dump('has variable `errno`:', $var);
echo '**********************' .PHP_EOL;
$var2 = $c->hasCVariable($ffi, 'error');
var_dump('=== has variable `error`:', $var2);

var_dump('has variable `error`:', $var2);
echo '**********************' .PHP_EOL;
$enum1 = $c->hasCEnum($ffi, 'ZEND_FFI_SYM_TYPE');
var_dump('has enum ZEND_FFI_SYM_TYPE:', $enum1);
echo '**********************' .PHP_EOL;
$rf = new ReflectionCFunction($ffi, 'gettimeofday');

$n = $rf->getNumberOfParameters();
var_dump('==== gettimeofday() num args:', $n);

var_dump('==== gettimeofday() is variadic:', $rf->isVariadic());

var_dump('gettimeofday() num args:', $n);
echo '**********************' .PHP_EOL;
var_dump('gettimeofday() is variadic:', $rf->isVariadic());
echo '**********************' .PHP_EOL;
$type = $rf->getReturnType();
var_dump('==== gettimeofday() return type:',$type);

var_dump('gettimeofday() return type:',$type);
echo '**********************' .PHP_EOL;
var_dump($rf->getParameters());

echo '**********************' .PHP_EOL;
$te = $ffi->type('te***');

var_dump('==== te type:', $c->getCTypeName($te));
var_dump('te type:', $c->getCTypeName($te));

0 comments on commit c09db87

Please sign in to comment.