Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need to return struct from the function. #8

Open
darkstarx opened this issue Oct 6, 2022 · 1 comment
Open

Need to return struct from the function. #8

darkstarx opened this issue Oct 6, 2022 · 1 comment

Comments

@darkstarx
Copy link

darkstarx commented Oct 6, 2022

Hello! Could you help me with structs?

I have a function like that

struct Offset2D
{
    double x;
    double y;
};

struct Offset2D createOffset2D(double x, double y);

How can I use this function with web_ffi? How should I change this code in Dart to work with Offset2D on the Dart side?

class Offset2D extends ffi.Struct {
  @ffi.Double()
  external double x;

  @ffi.Double()
  external double y;
}
@darkstarx
Copy link
Author

Ok, I got it. The only way now is to use c-style opaque structures like this:

.h

struct Offset2D;

DART_EXTERN_C
struct Offset2D* createOffset2D(double x, double y);

DART_EXTERN_C
void destroyOffset2D(struct Offset2D * const inst);

DART_EXTERN_C
double offset2DGetX(const struct Offset2D * const inst);

DART_EXTERN_C
double offset2DGetY(const struct Offset2D * const inst);

.c

struct Offset2D
{
    double x;
    double y;
};


DART_EXTERN_C
struct Offset2D* createOffset2D(const double x, const double y)
{
    struct Offset2D *offset = calloc(1, sizeof(struct Offset2D));
    offset->x = x;
    offset->y = y;
    return offset;
}


DART_EXTERN_C
void destroyOffset2D(struct Offset2D * const inst)
{
    if (inst) {
        free(inst);
    }
}


DART_EXTERN_C
double offset2DGetX(const struct Offset2D * const inst)
{
    if (inst) return inst->x;
    return 0.0;
}

DART_EXTERN_C
double offset2DGetY(const struct Offset2D * const inst)
{
    if (inst) return inst->y;
    return 0.0;
}

and binding like that
.dart

import 'proxy_ffi.dart' as ffi;

/// Bindings to common structs and funcs.
class NativeCommon {
  /// Holds the symbol lookup function.
  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
      _lookup;

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

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

  ffi.Pointer<Offset2D> createOffset2D(
    double x,
    double y,
  ) {
    return _createOffset2D(
      x,
      y,
    );
  }

  late final _createOffset2DPtr = _lookup<
      ffi.NativeFunction<
          ffi.Pointer<Offset2D> Function(
              ffi.Double, ffi.Double)>>('createOffset2D');
  late final _createOffset2D = _createOffset2DPtr
      .asFunction<ffi.Pointer<Offset2D> Function(double, double)>();

  void destroyOffset2D(
    ffi.Pointer<Offset2D> inst,
  ) {
    return _destroyOffset2D(
      inst,
    );
  }

  late final _destroyOffset2DPtr =
      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<Offset2D>)>>(
          'destroyOffset2D');
  late final _destroyOffset2D =
      _destroyOffset2DPtr.asFunction<void Function(ffi.Pointer<Offset2D>)>();

  double offset2DGetX(
    ffi.Pointer<Offset2D> inst,
  ) {
    return _offset2DGetX(
      inst,
    );
  }

  late final _offset2DGetXPtr =
      _lookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<Offset2D>)>>(
          'offset2DGetX');
  late final _offset2DGetX =
      _offset2DGetXPtr.asFunction<double Function(ffi.Pointer<Offset2D>)>();

  double offset2DGetY(
    ffi.Pointer<Offset2D> inst,
  ) {
    return _offset2DGetY(
      inst,
    );
  }

  late final _offset2DGetYPtr =
      _lookup<ffi.NativeFunction<ffi.Double Function(ffi.Pointer<Offset2D>)>>(
          'offset2DGetY');
  late final _offset2DGetY =
      _offset2DGetYPtr.asFunction<double Function(ffi.Pointer<Offset2D>)>();
}

// ignore: subtype_of_sealed_class
class Offset2D extends ffi.Opaque {}

By the way, why Opaque type is sealed? How to use it without extending? I wonder it because I have to register every opaque structure with registerOpaqueType method. So, what's the point?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant