berry icon indicating copy to clipboard operation
berry copied to clipboard

Constructor that take ptr as argument never called

Open AlixANNERAUD opened this issue 1 year ago • 17 comments

Here is the following berry code :

Foo = Get_Ptr()
print(Foo) # print : <ptr: 0x3fca0a64> for example

Bar = Module.Test(Foo) #Class constructor taking pointer as argument
Bar = Module.Test(15)

The constructor is declared as CTYPE_FUNC with berry mapping as follows :

class Test_Class()
{
// Stuf here
};

void* Test_Init(bvm* VM, void* PTR)
{
Log_Format("Test_Init with ptr : %p", PTR);
return be_malloc(VM, sizeof(Test_Class));
}
BE_FUNC_CTYPE_DECLARE(Test_Init, "+_p", "@.")

// Berry mapping @const_object_info_begin declaration of the class and module

Once the code is ran, Bar = Test(Foo) is never called, but Bar = Test(15) is (of course invalid). I don't understand why, since there's no type checking on the last argument. It's maybe related to berry mapping ? I didn't get any exception thrown by the VM.

AlixANNERAUD avatar May 19 '23 16:05 AlixANNERAUD

Oh, I realize this is a leftover from early LVGL mapping. This is not documented, but currently when you pass a comptr to a constructor, it is directly assigned to the variable and the function is not called.

I think I should change this to not call the function only if the pointer to the function is NULL. Let me check.

s-hadinger avatar May 19 '23 19:05 s-hadinger

That would be great ! Thank you for your quick answer.

AlixANNERAUD avatar May 19 '23 19:05 AlixANNERAUD

Update ?

AlixANNERAUD avatar May 21 '23 10:05 AlixANNERAUD

Sorry not yet. I tried a quick fix but it failed

s-hadinger avatar May 21 '23 20:05 s-hadinger

I'm sorry but I didn't find any good way to solve it.

In LVGL, I typically need to call a native constructor in "C" with the following construct: int be_ntv_lv_obj_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_obj_create, "+_p", "(lv.lv_obj)"); }

However there are some cases when I just need to clone an existing object and not call the constructor. This is way there is a special behavior: when you call a constructor with a comptr argument, it just stores the reference and does not call the constructor.

I can't think of any alternative way to call the Berry constructor and not trigger the C constructor.

s-hadinger avatar May 22 '23 07:05 s-hadinger

Can you elaborate more about what you need? Can you make sure you don't send a comptr as first argument?

s-hadinger avatar May 22 '23 19:05 s-hadinger

Well, since in my case the comptr point to an object allocated outside Berry, it cannot be passed as a class instance to berry because the GC will clean it. Unless there is another way to practice, I don't see how else. However I totally understand the mechanism, and yes indeed, it makes sense.

AlixANNERAUD avatar May 22 '23 19:05 AlixANNERAUD

My point is that it would work if you pass a dummy first argument, and the comptr as a second argument.

s-hadinger avatar May 22 '23 19:05 s-hadinger

Ok, well, thank you, I will try to do it like that.

AlixANNERAUD avatar May 22 '23 19:05 AlixANNERAUD

If you allocate memory outside of Berry but still want to benefit from the GC, you can use comobj. comobj are managed by GC and you register a function that will be called when memory is deallocated.

s-hadinger avatar May 22 '23 20:05 s-hadinger

Comobj ? Do you have the link to its documentation ?

AlixANNERAUD avatar May 22 '23 20:05 AlixANNERAUD

The way I do in Tasmota:


/* generic destroy method for comobj, just call be_os_free() on the pointer */
int be_commonobj_destroy_generic(bvm* vm)
{
    int argc = be_top(vm);
    if (argc > 0) {
        void * obj = be_tocomptr(vm, 1);
        if (obj != NULL) { be_os_free(obj); }
    }
    be_return_nil(vm);
}

And then I can allocate an object. Example from Tasmota crypto:

[...]
    // Initialize an AES CTR structure with the secret key
    br_aes_small_ctr_keys * ctr_ctx = (br_aes_small_ctr_keys *) be_os_malloc(sizeof(br_aes_small_ctr_keys));
    if (!ctr_ctx) { be_throw(vm, BE_MALLOC_FAIL); }
[...]
    be_newcomobj(vm, ctr_ctx, &be_commonobj_destroy_generic);
    be_setmember(vm, 1, ".p1");
[...]

s-hadinger avatar May 22 '23 20:05 s-hadinger

Comobj ? Do you have the link to its documentation ?

Unfortunately documentation of comobj is missing. I inferred it from the source.

s-hadinger avatar May 22 '23 20:05 s-hadinger

Thank you, however, I don't think this is suitable for my use. I especially don't want my object, allocated outside of berry, to be deallocated as it is also used outside of the VM.

AlixANNERAUD avatar May 22 '23 20:05 AlixANNERAUD

Ok, got it. Then comptr is the right way.

s-hadinger avatar May 22 '23 20:05 s-hadinger

Thank you, however, this will be very useful to me because I have other cases where it can be useful.

AlixANNERAUD avatar May 22 '23 20:05 AlixANNERAUD

I tried to pass an instance of an object as the first argument parameter, and I get the same behaviour. Same thing when adding a dummy boolean argument.

AlixANNERAUD avatar May 23 '23 17:05 AlixANNERAUD