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

/// Bindings to `headers/example.h`.
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;

  /// Adds 2 integers.
  int sum(
    int a,
    int b,
  ) {
    return _sum(
      a,
      b,
    );
  }

  late final _sum_ptr = _lookup<ffi.NativeFunction<_c_sum>>('sum');
  late final _dart_sum _sum = _sum_ptr.asFunction<_dart_sum>();

  /// Subtracts 2 integers.
  int subtract(
    ffi.Pointer<ffi.Int32> a,
    int b,
  ) {
    return _subtract(
      a,
      b,
    );
  }

  late final _subtract_ptr =
      _lookup<ffi.NativeFunction<_c_subtract>>('subtract');
  late final _dart_subtract _subtract =
      _subtract_ptr.asFunction<_dart_subtract>();

  /// Multiplies 2 integers, returns pointer to an integer,.
  ffi.Pointer<ffi.Int32> multiply(
    int a,
    int b,
  ) {
    return _multiply(
      a,
      b,
    );
  }

  late final _multiply_ptr =
      _lookup<ffi.NativeFunction<_c_multiply>>('multiply');
  late final _dart_multiply _multiply =
      _multiply_ptr.asFunction<_dart_multiply>();

  /// Divides 2 integers, returns pointer to a float.
  ffi.Pointer<ffi.Float> divide(
    int a,
    int b,
  ) {
    return _divide(
      a,
      b,
    );
  }

  late final _divide_ptr = _lookup<ffi.NativeFunction<_c_divide>>('divide');
  late final _dart_divide _divide = _divide_ptr.asFunction<_dart_divide>();

  /// Divides 2 floats, returns a pointer to double.
  ffi.Pointer<ffi.Double> dividePercision(
    ffi.Pointer<ffi.Float> a,
    ffi.Pointer<ffi.Float> b,
  ) {
    return _dividePercision(
      a,
      b,
    );
  }

  late final _dividePercision_ptr =
      _lookup<ffi.NativeFunction<_c_dividePercision>>('dividePercision');
  late final _dart_dividePercision _dividePercision =
      _dividePercision_ptr.asFunction<_dart_dividePercision>();
}

typedef _c_sum = ffi.Int32 Function(
  ffi.Int32 a,
  ffi.Int32 b,
);

typedef _dart_sum = int Function(
  int a,
  int b,
);

typedef _c_subtract = ffi.Int32 Function(
  ffi.Pointer<ffi.Int32> a,
  ffi.Int32 b,
);

typedef _dart_subtract = int Function(
  ffi.Pointer<ffi.Int32> a,
  int b,
);

typedef _c_multiply = ffi.Pointer<ffi.Int32> Function(
  ffi.Int32 a,
  ffi.Int32 b,
);

typedef _dart_multiply = ffi.Pointer<ffi.Int32> Function(
  int a,
  int b,
);

typedef _c_divide = ffi.Pointer<ffi.Float> Function(
  ffi.Int32 a,
  ffi.Int32 b,
);

typedef _dart_divide = ffi.Pointer<ffi.Float> Function(
  int a,
  int b,
);

typedef _c_dividePercision = ffi.Pointer<ffi.Double> Function(
  ffi.Pointer<ffi.Float> a,
  ffi.Pointer<ffi.Float> b,
);

typedef _dart_dividePercision = ffi.Pointer<ffi.Double> Function(
  ffi.Pointer<ffi.Float> a,
  ffi.Pointer<ffi.Float> b,
);
