Help interfacing with C function and input parameters format
-
- Posts: 1
- Joined: Mon Dec 03, 2018 3:10 pm
Help interfacing with C function and input parameters format
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
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
Re: Help interfacing with C function and input parameters format
Yes I’ll help.
Putting this here as a reminder to myself.
Sent from my iPhone using Tapatalk Pro
Putting this here as a reminder to myself.
Sent from my iPhone using Tapatalk Pro
Help interfacing with C function and input parameters format
In .py context, a list is different from an array.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:
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
void foo(double [] arg1, double [] arg2, double [] arg3)
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
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);
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?Code: Select all
mp_obj_list_get(args[1], &len_arg1, &arg1);
Thank you
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
Re: Help interfacing with C function and input parameters format
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.
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.
Re: Help interfacing with C function and input parameters format
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 :
why we need to use and not ?
2. In order to get a C array of float can I do something like :
I'm feeling I'm missing something but can't get my head around it yet.
Thank you
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);
Code: Select all
const mp_obj_t arg1
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;
}
Thank you
Re: Help interfacing with C function and input parameters format
Can you give an example of where that is required?why we need to use const mp_obj_t arg1
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.float features[];
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
Re: Help interfacing with C function and input parameters format
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);
"
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);
"
Re: Help interfacing with C function and input parameters format
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.
Re: Help interfacing with C function and input parameters format
hello,
I have tried your second recommendation but I get the following error at compilation :
my C code looks like this :
What am I doing wrong?
Thanks
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
};
Thanks
Re: Help interfacing with C function and input parameters format
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.