While attempting this I ran into the need to use GC_ADDREF() or else the
returned sub-object data would be gargled.  Here is an example struct:

typedef struct _php_raylib_camera2d_object {
    Camera2D camera2d;
    HashTable *prop_handler;
    php_raylib_vector2_object *offset;
    php_raylib_vector2_object *target;
    zend_object std;
} php_raylib_camera2d_object;


When I returned a say "target" i.e:

static zend_object * php_raylib_camera2d_target(php_raylib_camera2d_object
*obj)
{
    return &obj->target->std;
}

In PHP the values would be incorrect. However by
adding GC_ADDREF(&obj->target->std), this seems to have fixed the problem.
So it now reads:

static zend_object * php_raylib_camera2d_target(php_raylib_camera2d_object
*obj)
{
    GC_ADDREF(&obj->target->std);
    return &obj->target->std;
}

However in PHP if someone is repeatedly access the subobject "target" does
this now much it will have many references? Will I need to manage those
references in my C code?

Here is the resulting object code in PHP:
<?php
$camera = new \raylib\Camera2d();

$camera->target->x = 5;
$camera->target->y = 6;

var_dump($camera->target);

Here "target" is accessed 3 times. Thats 3 additional reference counts. If
I unset($camera),  do I now need to manage those references and
explicitly call GC_DELREF/GC_SET_REFCOUNT in my `free_obj` function?

Thanks,
Joseph Montanez


On Tue, Mar 9, 2021 at 10:09 PM Joseph Montanez <sut...@gmail.com> wrote:

> Michael,
>
> Thanks for the feedback! The part about having Zend Object at the end of a
> struct saved me because I was starting to have issues with cloning objects.
>
> This is for an extension I was working on and have picked back up, I was
> just isolating it to make it easy to work with. Its bindings for
> https://www.raylib.com/. The general issue is that I won't be able to
> change RayLib's structs (embedded vs pointers), so what I showed was an
> isolated example. There is another author who also has a RayLib binding in
> PHP and has a similar issue:
>
> https://github.com/oraoto/raylib-phpcpp
> <?php
>
> $v = Vector2(1, 2);
> // $v->x += 1; doesn't work
> $v->x = $v->x + 1;
>
> $camera = Camera2D(Vector2(1, 1), Vector2(0, 0), 1.0, 1.0);
> // $camera->target->x = 1; // doesn't work
> $target = $camera->target;
> $target->x = 1;
> $camera->target = $target;
>
> This is far from ideal, and I can only assume people will run into this
> and assume it's a bug. On my end, I've written my own (incomplete) bindings
> https://github.com/joseph-montanez/raylib-php |
> https://joseph-montanez.github.io/raylib-php-docs/ I am working towards
> those issues, this is just a stumbling block.
>
> The more I think about this, I probably don't need a listening system,
> rather when the object is used for an internal RayLib function call, I can
> unravel the sub-objects and write back to the original struct. For example
> in RayLib there is a function DrawRay(Ray ray, Color color), when I
> implement DrawRay, I can do the unravel work to pull the values from
> position and direction PHP objects back into the Ray struct, and then pass
> the Ray struct to DrawRay.
>
>
>
> Thanks,
> Joseph Montanez
>
>
> On Tue, Mar 9, 2021 at 3:03 AM Michael Wallner <m...@php.net> wrote:
>
>> Hi Joseph!
>>
>> Is this for educational purposes or real world usage?
>>
>> I ask, because, if you don't have to adhere to a predefined C-API you
>> would avoid lots of headache by baking all this stuff into your PHP
>> objects with the APIs provided by Zend. But then again, it would be way
>> more efficient to just write it all in PHP code.
>>
>> More comments following inline.
>>
>> On 09/03/2021 03.32, Joseph Montanez wrote:
>> > I am not sure what to title this but the gist is that I have two structs
>> > with a one way dependency:
>> >
>> > // Vector3 type
>> > typedef struct Vector3 {
>> >     float x;
>> >     float y;
>> >     float z;
>> > } Vector3;
>> >
>> > // Ray type (useful for raycast)
>> > typedef struct Ray {
>> >     Vector3 position;       // Ray position (origin)
>> >     Vector3 direction;      // Ray direction
>> > } Ray;
>>
>> As these are embedded structs instead of pointers to, neither do point
>> to the memory of the other.
>>
>>
>> > The PHP Ray object is defined as so:
>> > typedef struct _skeleton_ray_object {
>> >     Ray ray;
>> >     HashTable *prop_handler;
>> >     zend_object std;
>>       ^^^^^^^^^^^^^^^^
>> NOTE: This has to be the last line in your object struct because of an
>> VLA at the end of the zend_object struct. See your xyz_new() function
>> where you allocate additional zend_object_properties_size() bytes for
>> that VLA (variable length array).
>>
>> >
>> >     skeleton_vector3_object *position;
>> >     skeleton_vector3_object *direction;
>> > } skeleton_ray_object;
>> >
>> > When I update either vector3 object, I don't have a way to propagate the
>> > changes back to the parent object(Ray). This means the raw Ray struct is
>> > never updated. Is there a built-in way to handle propagation
>> (listeners) in
>> > a PHP extension or will I need to hand roll this?
>>
>> Yes, you gotta write all of this on your own, but let me repeat that
>> this is a lot of boilerplate which also may entail lots of headache.
>>
>>
>> --
>> Regards,
>> Mike
>>
>>

Reply via email to