How to deal with C source libraries with `static inline` header functions?
arkanoid87 opened this issue · 4 comments
I was trying to wrap LVGL and implement original hello_world.c in Nim.
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_LABEL
/**
* Basic example to create a "Hello world" label
*/
void lv_example_get_started_1(void)
{
/*Change the active screen's background color*/
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x003a57), LV_PART_MAIN);
/*Create a white label, set its text and align it to the center*/
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Hello world");
lv_obj_set_style_text_color(lv_scr_act(), lv_color_hex(0xffffff), LV_PART_MAIN);
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}
#endif
This library is intended to be compiled with the project source, and has many static inline
functions in header files, for example
lv_color_hex
inlined functions are skipped by futhark and never wrapped, and it makes generally sense when linking, but what should I do when the project importing the library is meant to call static inline header functions?
I tried, just for quick test, commenting out if node["inlined"].getBool: return
Compiling this file:
import futhark
importc:
path "../lvgl"
path "../lvgl/src/misc"
path "../lvgl/src/core"
"lvgl.h"
"lv_color.h"
"lv_obj_style_gen.h"
Resulted in clang complaining many redefinitions
Error: Opir exited with non-zero exit code 255.
Opir output:
Warning: Possible failure to include lv_conf.h, please read the comment in this file if you get errors
Error: redefinition of 'lv_obj_get_style_width'
Error: redefinition of 'lv_obj_get_style_min_width'
Error: redefinition of 'lv_obj_get_style_max_width'
Error: redefinition of 'lv_obj_get_style_height'
Error: redefinition of 'lv_obj_get_style_min_height'
Error: redefinition of 'lv_obj_get_style_max_height'
Error: redefinition of 'lv_obj_get_style_x'
Error: redefinition of 'lv_obj_get_style_y'
Error: redefinition of 'lv_obj_get_style_align'
Error: redefinition of 'lv_obj_get_style_transform_width'
Error: redefinition of 'lv_obj_get_style_transform_height'
Error: redefinition of 'lv_obj_get_style_translate_x'
Error: redefinition of 'lv_obj_get_style_translate_y'
Error: redefinition of 'lv_obj_get_style_transform_zoom'
Error: redefinition of 'lv_obj_get_style_transform_angle'
Error: redefinition of 'lv_obj_get_style_transform_pivot_x'
Error: redefinition of 'lv_obj_get_style_transform_pivot_y'
Error: redefinition of 'lv_obj_get_style_pad_top'
Error: redefinition of 'lv_obj_get_style_pad_bottom'
Fatal: too many errors emitted, stopping now
Is there a designed way to apply Futhark in this context?
The reason inlined
weren't generated to begin with is because it makes no sense when dynamically linking. I don't quite remember if this was a matter of actually finding these in a header meant for dynamic linking, or if this was just me being cautious. But for compiling together with the sources it doesn't make sense to omit them.
I've pushed a new version 0.9.3 which adds the -d:generateInline
flag. Along with this code:
import futhark
importc:
path "../lvgl"
"lvgl.h"
lvObjSetStyleBgColor(lvScrAct(), lvColorHex(0x003a57), LV_PART_MAIN.lvStyleSelectorT)
it now fails on the C building step (because I didn't tell it how to actually link with lvgl). If you get something set up with LVGL I would love to see the results :)
Thank you for addressing this
I can confirm that using -d:generateInline
I end up with linking errors, but the errors are about linker not finding inlined functions in header, for example:
@mtest_lvgl.nim.c:(.text+0xee): undefined reference to `lv_scr_act'
defined in src/disp/lv_disp.h
https://github.com/lvgl/lvgl/blob/1c1b59988004622de564b2655af56757ece00182/src/disp/lv_disp.h#L373
Afaik compiling LVGL C files into a static or dynamic library file is not the way, as inlined functions wont be there anyway. I'd guess that the right way is to add the header
pragma to inlined functions
I've tried (using outputPath) to manually add it to generate lv_scr_act
function:
proc lvscract*(): ptr lvobjt_469762759 {.cdecl, header: "../lvgl/src/core/lv_disp.h", importc: "lv_scr_act".}
but I get conflicting types
test_lvgl_d/@mtest_lvgl.nim.c:83:15: error: conflicting types for ‘lv_obj_set_style_bg_color’; have ‘void(tyObject_structlvobjt469762586__9bfZUyxszOQcFM5H1JhlJQw *, tyObject_lvcolor16t469762490__J1gTOGAA6so8WXGapvAg1w, NU32)’ {aka ‘void(tyObject_structlvobjt469762586__9bfZUyxszOQcFM5H1JhlJQw *, tyObject_lvcolor16t469762490__J1gTOGAA6so8WXGapvAg1w, unsigned int)’}
83 | N_CDECL(void, lv_obj_set_style_bg_color)(tyObject_structlvobjt469762586__9bfZUyxszOQcFM5H1JhlJQw* obj, tyObject_lvcolor16t469762490__J1gTOGAA6so8WXGapvAg1w value, NU32 selector);
Am I missing something? How are inlined functions in .h files supposed to be used/imported in Nim code, without Futhark?
Hmm, header should remove the declaration. Maybe having both cdecl and header confuses it. Try removing cdecl and see if that helps.
Did you ever get a chance to test this?
EDIT: Just did some quick and dirty testing with a hand written Nim file and .h file. I can't get it to create any definition for my procedure when using the header
pragma. Maybe this is a bug fixed in recent versions of Nim, which version are you running?