dart-lang / native

Dart packages related to FFI and native assets bundling.
BSD 3-Clause "New" or "Revised" License
149 stars 42 forks source link

[ffigen] Support more MACROS #1066

Open dcharkes opened 6 months ago

dcharkes commented 6 months ago

We have support for macros that are direct constants:

But maybe we can do better and try to support more expressions and macros referring to macros.

// minwindef.h

#define MAKEWORD(a, b)      ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))
#define MAKELONG(a, b)      ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
#define LOWORD(l)           ((WORD)(((DWORD_PTR)(l)) & 0xffff))
#define HIWORD(l)           ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
#define LOBYTE(w)           ((BYTE)(((DWORD_PTR)(w)) & 0xff))
#define HIBYTE(w)           ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff))

Maybe @mannprerak2 can give some insight on what would or would not be possible.

We're happy to receive contributions if anyone wants to take a stab at this. Relevant code:

mannprerak2 commented 6 months ago

I think we are already able to parse all non functional macros. Since we create a new cpp file and create variables for each macro and let libclang handle parsing and simply fetch that variable's value.

Any functional macros would require us to parse the underlying tokens directly.

Edit: I assume we're talking about parsing functional macros as helper functions in dart, anything constant at compile time should probably already work (unless there's an issue with include headers)

tgrushka commented 2 days ago

This is really awesome! Would be amazing if possible to transform macros into enums.

e.g. FFmpeg has 28 AVERROR_.* codes that map to various integers that just get generated as Dart constants (imagine writing a case switch manually and keeping it up to date):

const int AVERROR_BUFFER_TOO_SMALL = -1397118274;
const int AVERROR_DECODER_NOT_FOUND = -1128613112;
const int AVERROR_DEMUXER_NOT_FOUND = -1296385272;

(I'm new to FFI and not terribly experienced in C projects; how common are these macros when enums really should have been used?)

Don't know if I know enough to take a stab at it, or how difficult it would be, but would be really nice to be able to have a config option to generate this instead:


enum AVError {
  AVERROR_BUFFER_TOO_SMALL(-1397118274),
  AVERROR_DECODER_NOT_FOUND(-1128613112),
  // ...
  AVERROR_EOF(-541478725),
  // ...

  static AVError fromValue(int value) => switch (value) {
        -1397118274 => AVERROR_BUFFER_TOO_SMALL,
        -1128613112 => AVERROR_DECODER_NOT_FOUND,
        // ...
        -541478725 => AVERROR_EOF,
        // ...
        _ => throw ArgumentError("Unknown value for AVError: $value"),
      };
}```