Recent

Author Topic: Best practice for using h2pas on a "clever" kernel interface binding  (Read 2662 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
With no particular urgency other than that it's been discussed in another thread, I'm taking a look at using libgpiod to interface to the "new" GPIO interface provided by Linux >=4.8. This is supposed to confer various advantages over the classic /sys/class/gpio which is now deprecated, my preference would be to invoke the kernel interface directly since that would avoid an external dependency but in the interim I'm considering a simple binding.

The problem is that gpiod.h uses various "clever" things beloved by the new generation of C/C++ programmers to apply various GCC-specific attributes etc., and h2pas doesn't like what it finds. I've tried running the .h file through the C preprocessor (cpp) and h2pas likes that even less.

What is best practice here: to manually substitute C macros etc. until h2pas runs without error?

Platform is Linux x86_64 on a PC, FPC 3.2.0.

MarkMLl


MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Bi0T1N

  • Jr. Member
  • **
  • Posts: 85
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #1 on: February 20, 2021, 02:23:53 pm »
In most cases h2pas can only convert simple header files without manual work. So it is to be expected that you need to adapt several parts of the converted unit.
For your unit:

For instance, sometimes it cannot convert things automatically and you've to convert it like
Code: C  [Select][+][-]
  1. /**
  2.  * @brief Open a gpiochip by path.
  3.  * @param path Path to the gpiochip device file.
  4.  * @return GPIO chip handle or NULL if an error occurred.
  5.  */
  6. struct gpiod_chip *gpiod_chip_open(const char *path);
just gives
Code: Pascal  [Select][+][-]
  1. (* error
  2. struct gpiod_chip *gpiod_chip_open(const char *path);
  3. in declaration at line 81 *)
so you need to adapt it to
Code: Pascal  [Select][+][-]
  1. function gpiod_chip_open(path:Pchar): Pgpiod_chip;

h2pas also seems to have issues with lines breaks/functions declarations over multiple lines (maybe it's also just because of the return type) as following functions are also not converted:
Code: C  [Select][+][-]
  1. struct gpiod_line *
  2. gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset);
  3.  
  4. struct gpiod_line_bulk *
  5. gpiod_chip_get_lines(struct gpiod_chip *chip, unsigned int *offsets,
  6.                      unsigned int num_offsets);
the converted unit just contains:
Code: Pascal  [Select][+][-]
  1. (* error
  2. struct gpiod_line *
  3. in declaration at line 117 *)
  4.  
  5. (* error
  6. struct gpiod_line_bulk *
  7. in declaration at line 128 *)

It also fails at converting the enums
Code: C  [Select][+][-]
  1. /**
  2.  * @brief Possible direction settings.
  3.  */
  4. enum {
  5.         GPIOD_LINE_DIRECTION_INPUT = 1,
  6.         /**< Direction is input - we're reading the state of a GPIO line. */
  7.         GPIOD_LINE_DIRECTION_OUTPUT,
  8.         /**< Direction is output - we're driving the GPIO line. */
  9. };
which should probably be a const in Pascal (or an enumerated type depending on what you favour) and converts the macro GPIOD_BIT into a function
Code: Pascal  [Select][+][-]
  1.     function GPIOD_BIT(nr : longint) : longint;
  2.     begin
  3.       GPIOD_BIT:=1 shl nr;
  4.     end;
instead of using it to calculate the appropriate numbers used in the C enum.

PS: I used h2pas -e -p -pr -s gpiod.h with the gpiod.h from the kernel git for the above examples.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #2 on: February 20, 2021, 02:44:11 pm »
In most cases h2pas can only convert simple header files without manual work. So it is to be expected that you need to adapt several parts of the converted unit.
For your unit:

Thanks for those (and the rest). I'd missed that there was a "less clever" implementation and I think it's telling that it was the kernel developers who insisted on it. I was going to start off with a manual substitution of that GPIOD_API, I'll come back to it later.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Bi0T1N

  • Jr. Member
  • **
  • Posts: 85
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #3 on: February 20, 2021, 03:29:17 pm »
In most cases h2pas can only convert simple header files without manual work. So it is to be expected that you need to adapt several parts of the converted unit.
For your unit:
I'd missed that there was a "less clever" implementation and I think it's telling that it was the kernel developers who insisted on it. I was going to start off with a manual substitution of that GPIOD_API, I'll come back to it later.
They simply removed the deprecated API function macro - probably with all the deprecated functions before it was added to the Linux kernel. ;)
The
Code: C  [Select][+][-]
  1. __attribute__ ((visibility ("default")))
macro seems quite useful (https://gcc.gnu.org/wiki/Visibility), so maybe h2pas should be updated so that it can detect and ignore it automatically as it'll probably be used more often in new header files.
Btw the libgpiod functionality seems to be quite nice and simple - maybe worth to add the translated header to FPC as a package?

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #4 on: February 20, 2021, 06:18:14 pm »
Btw the libgpiod functionality seems to be quite nice and simple - maybe worth to add the translated header to FPC as a package?

Maybe, but my preference would be to transcribe the binding to Pascal to remove the dependency on an external library... at least for my own use.

By and large I've found iopl interfaces to be fairly stable and easy to redo, with the notable exception of some (IIRC) hidraw stuff which had so many packing peculiarities that there really was no alternative to using something compiled by the same tools as the kernel.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #5 on: February 21, 2021, 09:52:02 pm »
In most cases h2pas can only convert simple header files without manual work. So it is to be expected that you need to adapt several parts of the converted unit.
For your unit:

The version I used initially was what's shipped with Debian, but it looks as though they're rather a long way behind the kernel.

H2pas works provided that GPIOD_API is removed, various struct* results are converted to psomething (psomething should not be predefined, h2pas prefers to translate an erroneous program) and the enums are replaced in situ with #defines.

I tried to take a look at the h2pas source to work out what it disliked about the enums but... well, I only hope its author can make more sense of it or we're all screwed.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #6 on: February 22, 2021, 09:15:10 am »
I tried to take a look at the h2pas source to work out what it disliked about the enums but... well, I only hope its author can make more sense of it or we're all screwed.
There are alternatives:
https://forum.lazarus.freepascal.org/index.php/topic,12763.msg66330.html#msg66330
https://github.com/WouterVanNifterick/C-To-Delphi
https://github.com/neslib/Chet

EDIT: Updated https://wiki.freepascal.org/C_to_Pascal with C-To-Delphi and Chet
« Last Edit: February 22, 2021, 09:48:18 am by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #7 on: February 22, 2021, 09:22:46 am »
I tried to take a look at the h2pas source to work out what it disliked about the enums but... well, I only hope its author can make more sense of it or we're all screwed.
There are alternatives:
https://forum.lazarus.freepascal.org/index.php/topic,12763.msg66330.html#msg66330
https://github.com/WouterVanNifterick/C-To-Delphi

Thanks very much, I've just eyeballed those and will take a more detailed look presently.

I'm going to tidy yesterday's conversion up manually and then try running it through my program that will generate static- and dynamically-linked interface units. https://forum.lazarus.freepascal.org/index.php/topic,53348.msg394506.html#msg394506

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #8 on: February 22, 2021, 09:34:09 am »
I tried to take a look at the h2pas source to work out what it disliked about the enums but... well, I only hope its author can make more sense of it or we're all screwed.

It utilizes the TPLY generator (in utils/tply) to generate the parser itself, so the main parser functionality is indeed... well... voodoo like. The "source" files for the parser are the h2pas.y and the scan.l.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #9 on: February 22, 2021, 09:46:46 am »
I tried to take a look at the h2pas source to work out what it disliked about the enums but... well, I only hope its author can make more sense of it or we're all screwed.

It utilizes the TPLY generator (in utils/tply) to generate the parser itself, so the main parser functionality is indeed... well... voodoo like. The "source" files for the parser are the h2pas.y and the scan.l.

Thanks for that. I saw it but couldn't work out how things hung together... my major focus at the time was trying to find the hidden option that caused h2pas to generate more useful error messages.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #10 on: February 22, 2021, 09:52:54 am »
Thanks very much, I've just eyeballed those and will take a more detailed look presently.
You're welcome. I've just updated the list with Chet which is worth looking at. It is libclang based so should be able to convert more then others. There's no perfect converter so I often combine results of 2-3 converters with some manual work.
« Last Edit: February 22, 2021, 09:54:57 am by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

ccrause

  • Hero Member
  • *****
  • Posts: 862
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #11 on: February 22, 2021, 10:53:11 am »
Subscribe. I also do header conversions from time to time and used h2pas in the past (because of the Lazarus integration).  H2pas does suffer for example when macro templates are used in e.g. struct definitions, and other annoyances that I've forgotten now.  Forced me to learn more about C and its macros than I thought I needed to know to work around the problems.

Would love to know which of the alternatives are worth pursuing.

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #12 on: February 22, 2021, 12:33:49 pm »
Would love to know which of the alternatives are worth pursuing.
Besides h2pas I use Chet, C To Pascal Converter and C-To-Delphi. I usually let them all do the work, and then compare source code side by side, and based on my personal preference I use bits of code from one or the other tool and mix them. Some tool makes nice structures, some other does a better job with defines, macros and enumerators, some produce more natural pascal like code and some produce c-like pascal code but can handle more code then others. That way up to 80-90% of C header conversion work can be automated.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #13 on: February 22, 2021, 02:52:38 pm »
Btw the libgpiod functionality seems to be quite nice and simple - maybe worth to add the translated header to FPC as a package?

Attached are static and dynamic interfaces for libgpiod in case anybody wants to play with them. They compile and the static version links, but I've not started significant testing yet and it will probably take me a bit of time to wrap my head round the API.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Best practice for using h2pas on a "clever" kernel interface binding
« Reply #14 on: February 22, 2021, 07:34:23 pm »
https://github.com/WouterVanNifterick/C-To-Delphi

I suspect that's probably deceptively flashy, and that a full language translator is probably overkill. But the obvious question is whether anybody's succeeded in compiling it with Lazarus/FPC.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018