// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;

/// Functions Test
class NativeLibrary {
  /// Holds the symbol lookup function.
  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
      _lookup;

  /// The symbols are looked up in [dynamicLibrary].
  NativeLibrary(ffi.DynamicLibrary dynamicLibrary)
      : _lookup = dynamicLibrary.lookup;

  /// The symbols are looked up with [lookup].
  NativeLibrary.fromLookup(
      ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
          lookup)
      : _lookup = lookup;

  void func1() {
    return _func1();
  }

  late final _func1_ptr =
      _lookup<ffi.NativeFunction<ffi.Void Function()>>('func1');
  late final _func1 = _func1_ptr.asFunction<void Function()>();

  int func2(
    int arg0,
  ) {
    return _func2(
      arg0,
    );
  }

  late final _func2_ptr =
      _lookup<ffi.NativeFunction<ffi.Int32 Function(ffi.Int16)>>('func2');
  late final _func2 = _func2_ptr.asFunction<int Function(int)>();

  double func3(
    double arg0,
    int a,
    int arg2,
    int b,
  ) {
    return _func3(
      arg0,
      a,
      arg2,
      b,
    );
  }

  late final _func3_ptr = _lookup<ffi.NativeFunction<Native_func3>>('func3');
  late final _func3 =
      _func3_ptr.asFunction<double Function(double, int, int, int)>();

  ffi.Pointer<ffi.Void> func4(
    ffi.Pointer<ffi.Pointer<ffi.Int8>> arg0,
    double arg1,
    ffi.Pointer<ffi.Pointer<ffi.Pointer<ffi.Int32>>> arg2,
  ) {
    return _func4(
      arg0,
      arg1,
      arg2,
    );
  }

  late final _func4_ptr = _lookup<ffi.NativeFunction<Native_func4>>('func4');
  late final _func4 = _func4_ptr.asFunction<
      ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Pointer<ffi.Int8>>, double,
          ffi.Pointer<ffi.Pointer<ffi.Pointer<ffi.Int32>>>)>();

  void func5(
    ffi.Pointer<shortHand> a,
    ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> b,
  ) {
    return _func5(
      a,
      b,
    );
  }

  late final _func5_ptr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(ffi.Pointer<shortHand>,
              ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>>('func5');
  late final _func5 = _func5_ptr.asFunction<
      void Function(ffi.Pointer<shortHand>,
          ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>();

  late final addresses = _SymbolAddresses(this);
}

class _SymbolAddresses {
  final NativeLibrary _library;
  _SymbolAddresses(this._library);
  ffi.Pointer<ffi.NativeFunction<Native_func3>> get func3 =>
      _library._func3_ptr;
  ffi.Pointer<ffi.NativeFunction<Native_func4>> get func4 =>
      _library._func4_ptr;
}

typedef Native_func3 = ffi.Double Function(
    ffi.Float arg0, ffi.Int8 a, ffi.Int64 arg2, ffi.Int32 b);
typedef Native_func4 = ffi.Pointer<ffi.Void> Function(
    ffi.Pointer<ffi.Pointer<ffi.Int8>> arg0,
    ffi.Double arg1,
    ffi.Pointer<ffi.Pointer<ffi.Pointer<ffi.Int32>>> arg2);
typedef shortHand = ffi.NativeFunction<
    ffi.Void Function(ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>;
