[SOLVED]Executing a method specified as a string of an mp_obj_t in C

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
BramPeeters
Posts: 49
Joined: Wed Jan 31, 2018 3:10 pm

[SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by BramPeeters » Thu Sep 20, 2018 11:00 pm

Hi,

I am looking for a way get 'PyObject_CallMethod' like functionality in micropython.
That is, I have an mp_obj_t and a method name (as a string), and now I would like to execute that function (or fail if the mp_obj_t does not support that particular method) (*).

Looking at the callstack coming out of the VM as inspiration I see that the entry point for executing functions is mp_call_method_n_kw, but for that I need to figure out the pointer to the function/method object corresponding to the type of mp_obj_t.

If I understand things correctly (with o being the mp_obj_t object):
(mp_map_lookup(MP_OBJ_TO_PTR(o)->base.type.locals_dict.map, mp_obj_new_str( strMyMethod, strlen(strMyMethod), 1), MP_MAP_LOOKUP ))->value
should give me that function object.

Is this more or less the way to do this ?
And maybe (hopefully) I am reinventing the wheel here and there is a nice 'PyObject_CallMethod' alternative already I overlooked ?

Thanks
Bram

(*) Sideremark: it does not really have to be a string, but since I do not want to limit which object type can be passed (any type which has the strMyMethod should be ok), I don't think there is an alternative ?
Last edited by BramPeeters on Fri Sep 21, 2018 8:50 am, edited 1 time in total.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Executing a method specified as a string of an mp_obj_t in C

Post by jickster » Thu Sep 20, 2018 11:20 pm

BramPeeters wrote:Hi,

I am looking for a way get 'PyObject_CallMethod' like functionality in micropython.
That is, I have an mp_obj_t and a method name (as a string), and now I would like to execute that function (or fail if the mp_obj_t does not support that particular method) (*).

Looking at the callstack coming out of the VM as inspiration I see that the entry point for executing functions is mp_call_method_n_kw, but for that I need to figure out the pointer to the function/method object corresponding to the type of mp_obj_t.

If I understand things correctly (with o being the mp_obj_t object):
(mp_map_lookup(MP_OBJ_TO_PTR(o)->base.type.locals_dict.map, mp_obj_new_str( strMyMethod, strlen(strMyMethod), 1), MP_MAP_LOOKUP ))->value
should give me that function object.

Is this more or less the way to do this ?
And maybe (hopefully) I am reinventing the wheel here and there is a nice 'PyObject_CallMethod' alternative already I overlooked ?

Thanks
Bram

(*) Sideremark: it does not really have to be a string, but since I do not want to limit which object type can be passed (any type which has the strMyMethod should be ok), I don't think there is an alternative ?
mp_load_method_maybe gets the function object and then you call the one you mentioned.

This function badly named because it applies to everything in local dict.

Also you have to use qstrings not strings.




Sent from my iPhone using Tapatalk Pro

BramPeeters
Posts: 49
Joined: Wed Jan 31, 2018 3:10 pm

Re: Executing a method specified as a string of an mp_obj_t in C

Post by BramPeeters » Fri Sep 21, 2018 8:50 am

Ah great ! That looks promising indeed ! Thanks!

('Also you have to use qstrings not strings.' -> Ok, so qstr_from_str/qstr_from_strn is my friend )

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: [SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by jickster » Sat Sep 22, 2018 1:32 am

BramPeeters wrote:Ah great ! That looks promising indeed ! Thanks!

('Also you have to use qstrings not strings.' -> Ok, so qstr_from_str/qstr_from_strn is my friend )
Q strings can never be deleted so they will take up increasing amount of ram if you keep on introducing new strings


Sent from my iPhone using Tapatalk Pro

BramPeeters
Posts: 49
Joined: Wed Jan 31, 2018 3:10 pm

Re: [SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by BramPeeters » Sun Sep 23, 2018 1:32 pm

Q strings can never be deleted so they will take up increasing amount of ram if you keep on introducing new strings
Yes, but in this case they are not new strings, they are method names that already exist as a qstring.
If i recall correctly qstr_from_str will first search if the string you pass already exists as a qstring and return that existing qstring, so no extra memory usage. Used in that way it is just a string to existing qstring conversion function.
Of course if the string is fixed I can immediately already use the qtring.
But for situation where the string is flexible qstr_from_str should do without memory leaking away....

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

[SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by jickster » Sun Sep 23, 2018 2:09 pm

What do you mean by your last sentence?

Anytime you use qstr_from_string on a new string, you’re leaking memory.


If you create a server-type application that accepts other .py files to execute, if those .py files use unique variable names eventually you will run out of heap from the qstrings eating up RAM.

If each .py only contains

Code: Select all

var = 1
And “var” is unique for each .py, you will eventually run out of heap.

Sent from my iPhone using Tapatalk Pro

BramPeeters
Posts: 49
Joined: Wed Jan 31, 2018 3:10 pm

Re: [SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by BramPeeters » Sun Sep 23, 2018 10:35 pm

What do you mean by your last sentence?
I don't currently have that situation (yet) but i can imagine having a situation where the method you need call is a string parameter (eg maybe it arrives from a remote server as a command or something ). In that case it will be hard for the server to know the qstring IDs so it will have to pass the real string .
And “var” is unique for each .py, you will eventually run out of heap.
Oh wow that is interesting!
[1] I want to support that the .py can be 'upgraded' , wich means completely stopping the old one and starting a new one. But then i need to find a way to 'purge' the VM to free up memory or reboot the device after such an update (not a bad idea in any case to start with a clean state)

[2] I was already wondering how the VM deals with running mp_call_function_0 again after the first one 'exits' but does not stop (so in relation with the other story where the first one launches threads that keep on living which i think might work if you would put the compiled bytecode in some marked memory area :) ). Do all the variables live in some shared memory area, or do they all live in their own context. I was kind of expecting that it was one big shared area and that each call of the mp_call_function_0 was REPL like, just adding to the common context. But that is not the case then ? And the dynamic qstrings exists only a single context ?
I am guessing it would be possible to 'feed' the contents of the .py's line per line to the REPL interpreter if one would really need the common context (I haven't looked at the REPL scenario at all so this is 100% uninformed speculation) ?

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: [SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by jickster » Mon Sep 24, 2018 1:00 am

I’m unsure if you’re asking me real questions or thinking out loud.


Sent from my iPhone using Tapatalk Pro

BramPeeters
Posts: 49
Joined: Wed Jan 31, 2018 3:10 pm

Re: [SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by BramPeeters » Mon Sep 24, 2018 10:01 am

No mostly thinking out loud, sorry.

But now I was looking for a way to purge the learned qstrings from
mp_state_ctx.vm.last_pool
to start 'fresh'.

As far as I can see there is not (yet) a function to do that ? So i would have to walk through the pool list myself to clear each pool ?

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: [SOLVED]Executing a method specified as a string of an mp_obj_t in C

Post by jickster » Mon Sep 24, 2018 11:50 am

Correct.


Sent from my iPhone using Tapatalk Pro

Post Reply