Help interfacing with C function and input parameters format

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
sigur_ros21
Posts: 1
Joined: Mon Dec 03, 2018 3:10 pm

Help interfacing with C function and input parameters format

Post by sigur_ros21 » Mon Dec 03, 2018 3:27 pm

Hi All,

I am relatively new to micropython and am struggling a bit trying to do the following. I have a series of functions implemented in C, which look like:

[code]
void foo(double [] arg1, double [] arg2, double [] arg3)
[/code]

I would like to create a micropython module that allows me to call such c function from the main .py that is running on an ESP32-based platform. So far, I have created such module, including methods that allow calling such c functions. For example:

[code]
STATIC mp_obj_t mymod_foo(size_t n_args, const mp_obj_t *args) {

mp_obj_t *arg1, *arg2, *arg3;
mp_uint_t len_arg1, len_arg1, len_arg3;
/* ToDo*/
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mymod_obj, 4, 4, mymod_foo);
[/code]

What I don't know is how to get double-type objects such that I can call the C-function foo(arg1, arg2, arg3). So far, I have tried things like:

[code]
mp_obj_list_get(args[1], &len_arg1, &arg1);
[/code]

which as expected copies whichever input list I have in args[1] in arg1 as well as extracts the length of such list. Nonetheless, what could I do next? How could I convert arg1 into an double-type array? Or is any other approach to do this?

Thank you

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

Re: Help interfacing with C function and input parameters format

Post by jickster » Tue Dec 04, 2018 6:18 pm

Yes I’ll help.

Putting this here as a reminder to myself.


Sent from my iPhone using Tapatalk Pro

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

Help interfacing with C function and input parameters format

Post by jickster » Mon Dec 17, 2018 5:10 am

sigur_ros21 wrote:Hi All,

I am relatively new to micropython and am struggling a bit trying to do the following. I have a series of functions implemented in C, which look like:

Code: Select all

void foo(double [] arg1, double [] arg2, double [] arg3)
I would like to create a micropython module that allows me to call such c function from the main .py that is running on an ESP32-based platform. So far, I have created such module, including methods that allow calling such c functions. For example:

Code: Select all

STATIC mp_obj_t mymod_foo(size_t n_args, const mp_obj_t *args) {

    mp_obj_t *arg1, *arg2, *arg3;
    mp_uint_t len_arg1, len_arg1, len_arg3;
    /* ToDo*/
    return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mymod_obj, 4, 4, mymod_foo);
What I don't know is how to get double-type objects such that I can call the C-function foo(arg1, arg2, arg3). So far, I have tried things like:

Code: Select all

    mp_obj_list_get(args[1], &len_arg1, &arg1);
which as expected copies whichever input list I have in args[1] in arg1 as well as extracts the length of such list. Nonetheless, what could I do next? How could I convert arg1 into an double-type array? Or is any other approach to do this?

Thank you
In .py context, a list is different from an array.

A python array can only contain one type of element ie float, double, int, char. That’s like what you expect from more strongly typed languages like C++.

A python list’s elements can be of completely different type.

If you wanna use list, make sure you pass in a list and not an array.

After you call mp_obj_list_get(), iterate over arg1 and pass arg1 to mp_obj_get_float.



Sent from my iPhone using Tapatalk Pro

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Help interfacing with C function and input parameters format

Post by dhylands » Tue Dec 18, 2018 1:47 am

All parameters which are passed from python need to be declared as mp_obj_t.

If you're going to pass each of arg1, arg2, arg3 as array objects, then your function declaration should look like:

STATIC mp_obj_t mymod_foo(const mp_obj_t arg1, const mp_obj_t arg2, const mp_obj_t arg3);

You would use a function like: mp_obj_get_array to determine how many elements are in arg1 and get a pointer to the array of objects in the array.

micropython doesn't differentiate between floats and doubles the same way that C does. The size of a floating point number depends on the format that's configured for the firmware. The various formats are described in py/mpconfig.h:
https://github.com/micropython/micropyt ... nfig.h#L52

For the pyboard, format A is the one used by default. Since the Cortex-M4 has native support for 32-bit floating point numbers, that's the size that used by default.

You'll use a type like mp_float_t rather than float or double.
https://github.com/micropython/micropyt ... fig.h#L588

I seem to recall that you can build for the pyboard using a double for float, but the performance drops considerably, since all of the floating point operations are now performed in software rather than by the hardware.

Keja
Posts: 12
Joined: Sat Dec 19, 2020 9:56 am

Re: Help interfacing with C function and input parameters format

Post by Keja » Wed Apr 21, 2021 7:12 pm

Hello,
I have a similar use case where I want to pass a list of floats to a C functions. I have a few questions :

1. In the function declaration below :

Code: Select all

STATIC mp_obj_t mymod_foo(const mp_obj_t arg1, const mp_obj_t arg2, const mp_obj_t arg3);
why we need to use

Code: Select all

const mp_obj_t arg1
and not

Code: Select all

mp_obj_t arg1
?

2. In order to get a C array of float can I do something like :

Code: Select all

STATIC mp_obj_t mymod_foo(const mp_obj_t mylist_in) {
  size_t len;
  float features[];  // this is the C array I need to call with my external C function
  mp_obj_get_array(mylist_in,*len, *features);
   myCFunction(features);
    return mp_const_none;
}
I'm feeling I'm missing something but can't get my head around it yet.


Thank you

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Help interfacing with C function and input parameters format

Post by stijn » Thu Apr 22, 2021 3:16 pm

why we need to use const mp_obj_t arg1
Can you give an example of where that is required?
float features[];
This is probably wrong (does this even compile?): mp_obj_get_array takes an mp_obj_t** as last argument, not a float*. Even if it doesn't cause undefined behavior, it might not get you the floating point values because a Python list is different from a C float array. The list is just a collection of pointers, each pointing to an actual object. Or in some cases the actual object, depending on MicroPython internal representation which you shouldn't rely one. Nothing guarantees that is an array of floating point values.

If you need an array of float then either:
- use the array module which gives a contiguous piece of memory so you're sure that in C you also get what you need; use mp_obj_is_type(o, &mp_type_array) to verify your argument has the correct type, cast to mp_obj_array_t, double-check the typecode, access the items
- allocate an array in C and fill each item in a loop where you call mp_obj_get_float on each list item (which you get from mp_obj_get_array )
- rewrite your C function to work one element at a time then use a loop like above again

Keja
Posts: 12
Joined: Sat Dec 19, 2020 9:56 am

Re: Help interfacing with C function and input parameters format

Post by Keja » Thu Apr 22, 2021 4:18 pm

thank you , what you wrote makes sense and will try it right away.

Regarding your first question I was referring to dhylands answer on this topic :

"If you're going to pass each of arg1, arg2, arg3 as array objects, then your function declaration should look like:

STATIC mp_obj_t mymod_foo(const mp_obj_t arg1, const mp_obj_t arg2, const mp_obj_t arg3);
"

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Help interfacing with C function and input parameters format

Post by stijn » Thu Apr 22, 2021 5:56 pm

That's a matter of preference. In C and C++ it's not bad to make everything possible const, but in this case it is not ideal since mp_obj_t can be a pointer, but not always (depending on platform). So it gives a mixed feeling of safety. I.e. if it's a pointer then it only guards you from writing *arg = ... but not from arg = &... . And most micropython functions also don't take const.

Keja
Posts: 12
Joined: Sat Dec 19, 2020 9:56 am

Re: Help interfacing with C function and input parameters format

Post by Keja » Fri Apr 23, 2021 11:29 am

hello,

I have tried your second recommendation but I get the following error at compilation :

Code: Select all

modrun.c:37:37: error: request for member 'items' in something not a structure or union
   37 | cfeatures[i]=mp_obj_get_int(features->items[i]);

my C code looks like this :

Code: Select all

STATIC mp_obj_t get_list(mp_obj_t pylistin) {
 
  size_t len;
  mp_obj_t *features;

  mp_obj_get_array(pylistin,&len, &features);

  int cfeatures[len]  ;

for (int i=0; i < len;++i)
{
cfeatures[i]=mp_obj_get_int(features->items[i]);

}
// at this point I thought I would have an array of int that I can use further


};
What am I doing wrong?

Thanks 🙏

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Help interfacing with C function and input parameters format

Post by stijn » Fri Apr 23, 2021 3:47 pm

Assuming in Python you're going to call get_list([0, 1, 2]) you just need mp_obj_get_int(features[ i ]) since features is already the pointer to the list items. Also you should use mp_int_t features[len] instead of int, because it depends on the specific platform what the integer representation is. And also put return mp_const_none; at the end (assuming the function doesn't return anything). If you go through the sourcecode of MicroPython you can see many examples of how these things are done.

Post Reply