Page 1 of 2

Calling a python function from C

Posted: Mon Feb 02, 2015 11:37 pm
by gshilling
I'm working on embedding micro python into another STM32 C application I have. I would like to be able to call functions in a python script file from the C application. Is there a call like PyObject_GetAttrString from CPython to get a pointer to a function that could then be feed into mp_call_function_n_kw?

Re: Calling a python function from C

Posted: Tue Feb 03, 2015 2:28 am
by dhylands
Here's an example of calling a python function from C:
https://github.com/micropython/micropyt ... pin.c#L118

If you search for mp_call_function in the stmhal directory you'll see several other examples.

Posted: Tue Feb 03, 2015 6:31 pm
by Damien
You might want to try mp_load_global to get a function (or other object) defined by a script.

Re: Calling a python function from C

Posted: Tue Feb 07, 2017 1:59 pm
by Tetraeder
I have a similar question to the thread topic:
I create for pyboard the frozen script -> own.py

Code: Select all

def test():
	print('hello test')
I created in stmhal the folder "scripts" and define in Makefile the FROZEN_DIR. Copied the own.py script in folder scripts.
compile-> repl -> works, with

Code: Select all

>>> import own  
>>> own.test()
hello test
>>>
but how can I call this function for example in main.c by "soft reset".
I tried:

Code: Select all

mp_call_function_0(MP_STATE_PORT(own_test))
but no output via repl.
Maybe I don't understand the function :?:

Re: Calling a python function from C

Posted: Tue Feb 07, 2017 5:33 pm
by dhylands
The real trick is that you need to register the function from python first so that C can get a pointer to the function.

Otherwise you need to import the module, and then dig the function out of the module, which is doable, just a bunch more code.

You could also do the equivalent to the do_str function in unix/main.c:
https://github.com/micropython/micropyt ... #L287-L290
and call:

Code: Select all

do_str("import own\nown.test()")
Disclaimer: I didn't actually test that.

boot.py and main.py both run as part of a soft-reset.

You need to ensure that you're calling it at the right place in main.c.
boot.py is run before USB is initialized. main.py is run after USB is initialized.

Re: Calling a python function from C

Posted: Fri Oct 20, 2017 3:04 pm
by jickster
dhylands wrote:
Tue Feb 03, 2015 2:28 am
Here's an example of calling a python function from C:
https://github.com/micropython/micropyt ... pin.c#L118

If you search for mp_call_function in the stmhal directory you'll see several other examples.
The link is dead. Please post another one showing how to call Python from C.

Re: Calling a python function from C

Posted: Fri Oct 20, 2017 5:23 pm
by benalb
[/quote]

The link is dead. Please post another one showing how to call Python from C.
[/quote]

I think this is the right link, with the changes in 1.9 tree:

https://github.com/micropython/micropyt ... pin.c#L118

Re: Calling a python function from C

Posted: Thu Dec 14, 2017 4:45 pm
by jickster
dhylands wrote:
Tue Feb 07, 2017 5:33 pm
The real trick is that you need to register the function from python first so that C can get a pointer to the function.

Otherwise you need to import the module, and then dig the function out of the module, which is doable, just a bunch more code.

You could also do the equivalent to the do_str function in unix/main.c:
https://github.com/micropython/micropyt ... #L287-L290
and call:

Code: Select all

do_str("import own\nown.test()")
Disclaimer: I didn't actually test that.

boot.py and main.py both run as part of a soft-reset.

You need to ensure that you're calling it at the right place in main.c.
boot.py is run before USB is initialized. main.py is run after USB is initialized.
How would I call gc_disable() from C?

Re: Calling a python function from C

Posted: Mon Dec 18, 2017 8:30 pm
by dhylands
An updated link to the pin.c file (which only moved by a single line) is:
https://github.com/micropython/micropyt ... pin.c#L119

Are you referring to this gc_disable function?
https://github.com/micropython/micropyt ... odgc.c#L45
which is what gets called when you do this in MicroPython:

Code: Select all

import gc
gc.disable()
I guess I would ask what is it that you're really trying to achieve?

To call that exact function from C, you need to locate the gc module, and then look up the disable method. The following:

Code: Select all

    mp_obj_t gc_module_obj = mp_module_get(MP_QSTR_gc);
    if (gc_module_obj) {
      mp_obj_t gc_disable_fn = mp_load_attr(gc_module_obj, MP_QSTR_disable);
      if (gc_disable_fn) {
        mp_call_function_0(gc_disable_fn);
      }
    }
worked for me.

Re: Calling a python function from C

Posted: Sat Mar 03, 2018 11:59 pm
by jickster
dhylands wrote:
Mon Dec 18, 2017 8:30 pm
An updated link to the pin.c file (which only moved by a single line) is:
https://github.com/micropython/micropyt ... pin.c#L119

Are you referring to this gc_disable function?
https://github.com/micropython/micropyt ... odgc.c#L45
which is what gets called when you do this in MicroPython:

Code: Select all

import gc
gc.disable()
I guess I would ask what is it that you're really trying to achieve?

To call that exact function from C, you need to locate the gc module, and then look up the disable method. The following:

Code: Select all

    mp_obj_t gc_module_obj = mp_module_get(MP_QSTR_gc);
    if (gc_module_obj) {
      mp_obj_t gc_disable_fn = mp_load_attr(gc_module_obj, MP_QSTR_disable);
      if (gc_disable_fn) {
        mp_call_function_0(gc_disable_fn);
      }
    }
worked for me.
I want to copy mp_obj_list_t. I know how to do it the long-way: use mp_map_lookup on mp_type_list.locals_dict and call MP_QSTR_copy. Is there a more direct way or do I have to make my own?
I followed through the execution path of mp_module_get(MP_QSTR_list) and it doesn't recurse into the builtins.

The list_copy function and struct are both static so I can't directly call them.

list_copy_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_type_list.locals_dict), MP_OBJ_NEW_QSTR(MP_QSTR_copy));
list_copy_obj->base.type->call(list_copy_obj, 1, 0, & self_can_msg->list_small_int);