google/webcrypto.dart

Use package:ffigen to generate bindings

Closed this issue ยท 6 comments

I've taken a stable at generating the bindings with package:ffigen.

With dart-lang/native#394 addressed, I can make it work on the host machine.

However, without addressing https://github.com/dart-lang/sdk/issues/36140 and https://github.com/dart-lang/native/issues/530, some of the integer sizes are not generated the right size for cross platform bindings.
// EVP_MD_size returns the digest size of |md|, in bytes.
OPENSSL_EXPORT size_t EVP_MD_size(const EVP_MD *md);

Handwritten bindings:

/// EVP_MD_size returns the digest size of md, in bytes.
///
/// ```c
/// size_t EVP_MD_size(const EVP_MD *md);
/// ```
final EVP_MD_size = resolve(Sym.EVP_MD_size)
    .lookupFunc<IntPtr Function(Pointer<EVP_MD>)>()
    .asFunction<int Function(Pointer<EVP_MD>)>();

Generated bindings (notice Uint64 instead of IntPtr):

  /// // EVP_MD_size returns the digest size of |md|, in bytes.
  int EVP_MD_size(
    ffi.Pointer<env_md_st> md,
  ) {
    return (_EVP_MD_size ??=
        _lookup<ffi.NativeFunction<_c_EVP_MD_size>>('EVP_MD_size')
            .asFunction<_dart_EVP_MD_size>())(
      md,
    );
  }

  _dart_EVP_MD_size? _EVP_MD_size;

typedef _c_EVP_MD_size = ffi.Uint64 Function(
  ffi.Pointer<env_md_st> md,
);

typedef _dart_EVP_MD_size = int Function(
  ffi.Pointer<env_md_st> md,
);

Edit: We have a workaround

typedef-map:
  'size_t': 'IntPtr`

Experiment: https://github.com/google/webcrypto.dart/tree/use-ffigen (ignore all the code duplication and pointer casts, I just wanted to migrate a single file).

@mannprerak2 please take a look at https://github.com/google/webcrypto.dart/tree/use-ffigen-2.

  • The structs CBS and CBB do not get any fields when I do not specify structs: - 'nothing' (see diff last commit). What behavior is causing this?
  • Can we filter constants? There are over 5000 in BoringSSL.

The structs CBS and CBB do not get any fields when I do not sp...

I can't seem to see any difference in the fields generated in the diff, could you copy the results from before and after?

Can we filter constants? There are over 5000 in BoringSSL.

Yes depending on the type, you can include/exclude unnamed-enums or macros.

can't seem to see any difference in the fields generated in the diff, could you copy the results from before and after?

My bad, I committed the one that I fixed up manually. It generated them as Opaque.

Yes depending on the type, you can include/exclude unnamed-enums or macros.

I forgot about that! ๐Ÿ˜…

Done. What about these duplicates? Probably generated because of multiple entry points.

const int ERR_LIB_HKDF = 31;
const int ERR_LIB_HKDF_1 = 31;
const int ERR_LIB_HKDF_2 = 31;
const int ERR_LIB_HKDF_3 = 31;
const int ERR_LIB_HKDF_4 = 31;
const int ERR_LIB_HKDF_5 = 31;
const int ERR_LIB_HKDF_6 = 31;
const int ERR_LIB_HKDF_7 = 31;
const int ERR_LIB_HKDF_8 = 31;
const int ERR_LIB_HKDF_9 = 31;
const int ERR_LIB_HKDF_10 = 31;
const int ERR_LIB_HKDF_11 = 31;

I also filed dart-lang/native#395 because many structs reference some other struct that I'm not interested in.

It's starting to look quite nice! ๐Ÿ˜ƒ

Done. What about these duplicates? Probably generated because of multiple entry points.

Ah, that's a bug. Since we use USR to remove duplicates, we mostly shoudln't get this issue even with multiple entry points.

It generated them as Opaque.

I've filled an issue for this dart-lang/native#397. This happened due to forward declarations, which were in the base.h file -

typedef struct cbb_st CBB;
typedef struct cbs_st CBS;

This goes away if the structs were excluded and hence only parsed when needed by any function.


Other notes: you should consider supplying -Wno-nullability-completeness in compiler-opts to remove null warnings from clang. I was also seeing stdarg.h not found on my system, If you were also seeing this you should resolve it soon or some missing types may randomly be assigned as Int32 by libclang.

-Wno-nullability-completeness

This has no effect for me with a newer Xcode (12.4).

stdarg.h

That's because the path to Xcode on my machine is hardcoded in compiler opts. ๐Ÿ™ˆ