Page 1 of 2

Using the C API?

Posted: Sat Feb 27, 2016 3:54 am
by hjf
Could anyone provide me with a small working example of what's discussed here? https://www.kickstarter.com/projects/21 ... sts/679050

Just a simple "Hello World!" function in C that I can call from Python, and the opposite as well.

Thanks!

Re: Using the C API?

Posted: Sat Feb 27, 2016 6:10 am
by dhylands
Here's a simple sample I put on a github branch:
https://github.com/dhylands/micropython ... 0d64ef7172

Here's the output from running it:

Code: Select all

>>> import c_sample
>>> def foo():
...     print('foo called')
... 
>>> c_sample.set_callback(foo)
>>> c_sample.call_callback()
foo called
And all of the peripherals are essentially similar. Look at things like stmhal/modpyb.c, or stmhal/timer.c (which has an example of calling python from C code).

Re: Using the C API?

Posted: Sat Feb 27, 2016 1:29 pm
by hjf
Thanks a lot!

Re: Using the C API?

Posted: Mon Feb 29, 2016 3:37 am
by hjf
I tried to base on your code to make a small function but I just can't seem to make it work.

I redefined your C function as:

Code: Select all

STATIC mp_obj_t c_sample_call_callback(void) {
    vstr_t vstr;
    vstr_init_fixed_buf(&vstr, 32, "some_string");

    mp_obj_t obj = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
    return mp_call_function_1(MP_STATE_PORT(c_sample_callback_obj),obj);

}
and the Python session looks like:

Code: Select all

MicroPython 84405ef-dirty on 2016-02-29; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> def a(b):
...     print(b)
...
...
...
>>> import c_sample
>>> c_sample.set_callback(a)
>>> c_sample.call_callback
<function>
What am I doing wrong?

Re: Using the C API?

Posted: Mon Feb 29, 2016 5:11 am
by dhylands
You're missing the parenthesis when you're trying to call the call_callback function. Instead of

Code: Select all

>>> c_sample.call_callback
you should be using

Code: Select all

>>> c_sample.call_callback()

Re: Using the C API?

Posted: Mon Feb 29, 2016 10:52 am
by hjf
dhylands wrote:You're missing the parenthesis when you're trying to call the call_callback function
Ah yes. Also known as the "don't try to program when it's 1AM and your eyes can't even focus on the screen"

But now I get this:

Code: Select all

>>> c_sample.call_callback()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError: memory allocation failed, allocating 1 bytes

Re: Using the C API?

Posted: Mon Feb 29, 2016 4:23 pm
by dhylands
You're misuing vstr. In particular, the vstr passed into mp_obj_new_str_from_vstr needs to be heap allocated.

You could use:

Code: Select all

STATIC mp_obj_t c_sample_call_callback(void) {
    mp_obj_t obj = mp_obj_new_str("some_string", strlen("some_string"), false);
    return mp_call_function_1(MP_STATE_PORT(c_sample_callback_obj), obj);
}
You'll need to also add a #include <string.h>. This produces:

Code: Select all

>>> def foo(b):
...     print(b)
... 
>>> import c_sample
>>> c_sample.set_callback(foo)
>>> c_sample.call_callback()
some_string
>>> 
If you wanted ot use a vstr, you'd need to do something like:

Code: Select all

STATIC mp_obj_t c_sample_call_callback(void) {
    vstr_t vstr;
    vstr_init_len(&vstr, strlen("some_string"));
    strcpy(vstr.buf, "some_string");
    mp_obj_t obj = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
    return mp_call_function_1(MP_STATE_PORT(c_sample_callback_obj), obj);
} 
which produces:

Code: Select all

>>> def foo(b):
...     print(b)
... 
>>> import c_sample
>>> c_sample.set_callback(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>> c_sample.set_callback(foo)
>>> c_sample.call_callback()
b'some_string'
mp_obj_t obj = mp_obj_new_str("some_string", strlen("some_string"), false);

Re: Using the C API?

Posted: Tue Jul 12, 2016 8:15 pm
by cduran
Could I add more C callbacks without modifying mpconfigport.h?

Re: Using the C API?

Posted: Tue Jul 12, 2016 9:25 pm
by dhylands
cduran wrote:Could I add more C callbacks without modifying mpconfigport.h?
You only need to modify mpconfigport.h to add the module. Once the module has been added you can add as many methods to the module that you want by just modifying c_sample.c (or whatever you call your module).

By convention, I probably should have called the source modsample.c.

Re: Using the C API?

Posted: Wed Jul 13, 2016 3:27 pm
by cduran
dhylands wrote:
cduran wrote:Could I add more C callbacks without modifying mpconfigport.h?
You only need to modify mpconfigport.h to add the module. Once the module has been added you can add as many methods to the module that you want by just modifying c_sample.c (or whatever you call your module).

By convention, I probably should have called the source modsample.c.
Wouldn't I also have to add the new callbacks to qstrdefsport.h?