php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #79066 Add interface to get memory address of FFI\CData
Submitted: 2020-01-05 07:20 UTC Modified: 2021-09-16 21:23 UTC
From: kentaro at ranvis dot com Assigned:
Status: Open Package: FFI (PECL)
PHP Version: 7.4.1 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: kentaro at ranvis dot com
New email:
PHP Version: OS:

 

 [2020-01-05 07:20 UTC] kentaro at ranvis dot com
Description:
------------
External libraries sometimes allow/require their clients to supply custom memory allocators so that they can behave nicely with the client applications.
When using such libraries in PHP FFI world, custom free() must iterate through malloc()ed memory one-by-one, comparing FFI\Cdata using == operator (to my knowledge):

$someLibMemMgmtStruct->malloc = function (int $size) use (&$memList) {
    $mem = $ffi->new("char[$size]");
    $ptr = FFI::addr($mem);
    $memList[] = [$ptr, $size, $mem];
    return $ptr;
};
$someLibMemMgmtStruct->free = function (FFI\Cdata $ptr) use (&$memList) {
    for ($i = count($memList); --$i >= 0; ) {
        if ($ptr == $memList[$i][0]) {
            array_splice($memList, $i, 1);
            return;
        }
    }
};

So it would be really helpful if FFI\Cdata has an interface to get a unique ID (e.g. memory address,) so that that ID can be used as a key when malloc() is called.

$someLibMemMgmtStruct->malloc = function (int $size) use (&$memList) {
    $mem = $ffi->new("char[$size]");
    $ptr = FFI::addr($mem);
    $memList[FFI::id($ptr)] = [$ptr, $size, $mem];
    return $ptr;
};
$someLibMemMgmtStruct->free = function (FFI\Cdata $ptr) use (&$memList) {
    unset($memList[FFI::id($ptr)]);
};

As another way of implementation, I considered of prepending an extra info when malloc()ed. But FFI\Cdata didn't like negative offset to be referenced...


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-01-06 09:23 UTC] kentaro at ranvis dot com
Update: I had missed the doc saying FFI\Cdata pointer address can be added/subtracted.
So what I wanted to do can be achieved like the below:

malloc:
 $mem = FFI::new("struct { int64_t id, size; char data[$size]; }");
 $ptr = FFI::addr($fragment->data);

free:
 $int64Align = FFI::alignof(FFI::type('int64_t'));
 $charAlign = FFI::alignof(FFI::type('char'));
 $offsetOfData = $int64Align * 2 + (($charAlign - ($int64Align * 2) % $charAlign) % $charAlign);
 $mem = FFI::cast('struct { int64_t id, size; } *', FFI::cast('char *', $ptr) - $offsetOfData);

Not as simple as I had expected for lack of FFI::offsetof() in this case.
 [2021-09-16 21:23 UTC] cmb@php.net
-Package: ffi +Package: FFI
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 20:01:29 2024 UTC