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

codegen produces dart code with incorrect types, including on examples - caused by external tool ffigen fail to find stdarg.h headers #53

Closed
gmorenz opened this issue Oct 11, 2021 · 28 comments
Labels
bug Something isn't working

Comments

@gmorenz
Copy link

gmorenz commented Oct 11, 2021

Hey, I'm trying to try this out, and I'm having an issue even get basic examples to work. The generated store_dart_post_cobject method has an incorrect type, resulting in an error:

lib/bridge_generated.dart:52:9: Error: The parameter 'ptr' of the method 'RustWire.store_dart_post_cobject' has type 'int', which does not match the corresponding type, 'Pointer<NativeFunction<Uint8 Function(Int64, Pointer<Void>)>>', in the overridden method, 'FlutterRustBridgeWireBase.store_dart_post_cobject'.
 - 'Pointer' is from 'dart:ffi'.
 - 'NativeFunction' is from 'dart:ffi'.
 - 'Uint8' is from 'dart:ffi'.
 - 'Int64' is from 'dart:ffi'.
 - 'Void' is from 'dart:ffi'.
Change to a supertype of 'Pointer<NativeFunction<Uint8 Function(Int64, Pointer<Void>)>>', or, for a covariant parameter, a subtype.
    int ptr,
        ^
../../../../.pub-cache/hosted/pub.dartlang.org/flutter_rust_bridge-1.0.3/lib/src/basic.dart:77:8: Context: This is the overridden method ('store_dart_post_cobject').
  void store_dart_post_cobject(

This happens even when trying to regenerate the example code! Is it possible the code generator is out of sync with the library code? (I installed it for these tests directly from the most recent master, but first ran into the issue with the version on crates.io)

Specifically for the example - running flutter_rust_bridge_codegen --rust-input rust/src/api.rs --dart-output dart/lib/bridge_generated.dart in frb_example/pure_dart/dart results in the non-whitespace changes (generated with: git diff -w --word-diff-regex='[^[:space:]]' lib/bridge_generated.dart) far below, and attempting to run the code results in the error immediately below:

+ dart compile exe lib/main.dart -o main.exe
Info: Compiling with sound null safety
lib/bridge_generated.dart:616:9: Error: The parameter 'ptr' of the method 'FlutterRustBridgeExampleWire.store_dart_post_cobject' has type 'int', which does not match the corresponding type, 'Pointer<NativeFunction<Uint8 Function(Int64, Pointer<Void>)>>', in the overridden method, 'FlutterRustBridgeWireBase.store_dart_post_cobject'.
 - 'Pointer' is from 'dart:ffi'.
 - 'NativeFunction' is from 'dart:ffi'.
 - 'Uint8' is from 'dart:ffi'.
 - 'Int64' is from 'dart:ffi'.
 - 'Void' is from 'dart:ffi'.
Change to a supertype of 'Pointer<NativeFunction<Uint8 Function(Int64, Pointer<Void>)>>', or, for a covariant parameter, a subtype.
    int ptr,
        ^
../../../frb_dart/lib/src/basic.dart:77:8: Context: This is the overridden method ('store_dart_post_cobject').
  void store_dart_post_cobject(
       ^
lib/bridge_generated.dart:98:15: Error: The argument type 'NativeFunction<Int32 Function(Pointer<Int32>)>' can't be assigned to the parameter type 'Pointer<NativeFunction<Int32 Function(Pointer<Int32>)>>'.
 - 'NativeFunction' is from 'dart:ffi'.
 - 'Int32' is from 'dart:ffi'.
 - 'Pointer' is from 'dart:ffi'.
              _api2wire_bool(myBool)),
              ^
lib/main.dart: Warning: Interpreting this as package URI, 'package:flutter_rust_bridge_example/main.dart'.
lib/main.dart:25:110: Error: The argument type 'bool' can't be assigned to the parameter type 'NativeFunction<Int32 Function(Pointer<Int32>)>'.
 - 'NativeFunction' is from 'dart:ffi'.
 - 'Int32' is from 'dart:ffi'.
 - 'Pointer' is from 'dart:ffi'.
        await api.primitiveTypes(myI32: 123, myI64: 10000000000000, myF64: 12345678901234567890.123, myBool: true), 42);
                                                                                                             ^
Error: AOT compilation failed
Generating AOT kernel dill failed!
  void wire_primitive_types(
    int port,
    int my_i32,
    int my_i64,
    double my_f64,
    {+ffi.Pointer<+}bool{+>+} my_bool,
  ) {
    return _wire_primitive_types(
      port,
  void wire_primitive_types(
    int port,
    int my_i32,
    int my_i64,
    double my_f64,
    {+ffi.Pointer<+}bool{+>+} my_bool,
  ) {
    return _wire_primitive_types(
      port,
      my_i32,
      my_i64,
      my_f64,
      my_bool[-? 1 : 0-],
    );
  }

  late final _wire_primitive_typesPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(ffi.Int64, ffi.Int32, ffi.Int64, ffi.Double,
              ffi.[-U-]{+Po+}int[-8-]{+er<bool>+})>>('wire_primitive_types');
  late final _wire_primitive_types = _wire_primitive_typesPtr
      .asFunction<void Function(int, int, int, double, {+ffi.Po+}int{+er<bool>+})>();
  void store_dart_post_cobject(
    [-DartPostCObjectF-]{+i+}n[-Type-]{+t+} ptr,
  ) {
  late final _store_dart_post_cobjectPtr =
      _lookup<ffi.NativeFunction<ffi.Void Function([-DartPostCObjectF-]{+ffi.I+}n[-Type-]{+t32+})>>(
          'store_dart_post_cobject');
  late final _store_dart_post_cobject =
      _store_dart_post_cobjectPtr.asFunction<void Function([-DartPostCObjectF-]{+i+}n[-Type-]{+t+})>();
}
typedef[-DartPostCO-] b[-jectFnType = ffi.P-]o[-inter<-]{+ol =+} ffi.NativeFunction<ffi.[-Ui-]{+I+}nt[-8-]{+32+} Function([-DartPort,-]ffi.Pointer<ffi.[-Void>)>>;-]
[-typedef DartPort = ffi.-]Int[-64-]{+32>)>+};
@gmorenz gmorenz added the bug Something isn't working label Oct 11, 2021
@welcome
Copy link

welcome bot commented Oct 11, 2021

Hi! Thanks for opening your first issue here! 😄

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

Hi, let me have a look.

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

could you plz provide

  • version of flutter_rust_bridge_codegen
  • run and paste flutter doctor -v
  • the whole generated code (you mention there are changes - so could you plz provide full change)
  • linux/mac/windows version
  • clang/clang++ version
  • also provide --c-output and paste that generated c header

It runs well on my machine, on GitHub CI's linux (ubuntu), macos, and windows. (see the CI workflow for your reference: https://github.com/fzyzcjy/flutter_rust_bridge/blob/master/.github/workflows/codegen.yml )So I guess there may be a configuration problem? Maybe also related to external tools like ffigen and cbindgen that I use internally. Thus more info is needed before I figure out what is happening.

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

By the way, that is most probably not problems in my code but problems related to ffigen/cbindgen. Since those "wire" things are not generated by my code, but generated by ffigen/cbindgen.

But of course I will debug it.

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

I'm happy to take a swing at debugging this if you would prefer, just wanted to confirm that it was actually a problem caused by my setup first.

OS is void linux, it's up to date and a normal enough rolling release linux distro (like arch) except for not using systemd (not relevant here).

$ flutter_rust_bridge_codegen --version
flutter_rust_bridge_codegen 1.0.3

Note, flutter_rust_bridge_codgen was installed from git commit e405c5c3b22554ed07dbc7729871aa5b1712bc30

$ clang --version
clang version 12.0.1
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /bin
$ cbindgen --version
cbindgen 0.20.0

(incidentally, cbindgen 0.19.0 doesn't work properly, I was failing with that earlier)

$ flutter doctor -v
[✓] Flutter (Channel stable, 2.5.2, on void 5.13.19_1, locale en_US.UTF-8)
    • Flutter version 2.5.2 at /home/greg/p/apps/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 3595343e20 (10 days ago), 2021-09-30 12:58:18 -0700
    • Engine revision 6ac856380f
    • Dart version 2.14.3

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✗] Chrome - develop for the web (Cannot find Chrome executable at google-chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[✓] Linux toolchain - develop for Linux desktop
    • clang version 12.0.1
    • cmake version 3.21.1
    • ninja version 1.10.2
    • pkg-config version 1.8.0

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).

[✓] Connected device (1 available)
    • Linux (desktop) • linux • linux-x64 • void 5.13.19_1

! Doctor found issues in 3 categories.

bridge_generated.log

(Note: Had to change extension from .dart to .log to get github to let me attach that)

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

I'm happy to take a swing at debugging this if you would prefer, just wanted to confirm that it was actually a problem caused by my setup first.

😄

Looking at your bridge_generated.dart it is quite strange (I paste below for convenience). It seems to not understand types. Moreover, seems that typedef bool = ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Int32>)>; - it thinks bool is a function...

Could you plz provide more info?

// AUTO GENERATED FILE, DO NOT EDIT.
// Generated by `flutter_rust_bridge`.

// ignore_for_file: non_constant_identifier_names, unused_element, duplicate_ignore, directives_ordering, curly_braces_in_flow_control_structures
import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter_rust_bridge/flutter_rust_bridge.dart';
import 'dart:ffi' as ffi;

abstract class FlutterRustBridgeExample
    extends FlutterRustBridgeBase<FlutterRustBridgeExampleWire> {
  factory FlutterRustBridgeExample(ffi.DynamicLibrary dylib) =>
      _FlutterRustBridgeExampleImpl.raw(FlutterRustBridgeExampleWire(dylib));

  FlutterRustBridgeExample.raw(FlutterRustBridgeExampleWire inner)
      : super(inner);

  Future<int> simpleAdder({required int a, required int b});

  Future<int> primitiveTypes(
      {required int myI32,
      required int myI64,
      required double myF64,
      required bool myBool});

  Future<String> handleString({required String s});

  Future<Uint8List> handleVecU8({required Uint8List v});

  Future<Uint8List> handleZeroCopyResult({required int n});

  Future<MySize> handleStruct({required MySize arg, required MySize boxed});

  Future<NewTypeInt> handleNewtype({required NewTypeInt arg});

  Future<List<MySize>> handleListOfStruct({required List<MySize> l});

  Future<MyTreeNode> handleComplexStruct({required MyTreeNode s});

  Future<int> returnErr();

  Future<int> returnPanic();
}

class MySize {
  final int width;
  final int height;

  MySize({
    required this.width,
    required this.height,
  });
}

class NewTypeInt {
  final int field0;

  NewTypeInt({
    required this.field0,
  });
}

class MyTreeNode {
  final int valueI32;
  final Uint8List valueVecU8;
  final List<MyTreeNode> children;

  MyTreeNode({
    required this.valueI32,
    required this.valueVecU8,
    required this.children,
  });
}

// ------------------------- Implementation Details -------------------------

class _FlutterRustBridgeExampleImpl extends FlutterRustBridgeExample {
  _FlutterRustBridgeExampleImpl.raw(FlutterRustBridgeExampleWire inner)
      : super.raw(inner);

  Future<int> simpleAdder({required int a, required int b}) => execute(
      (port) =>
          inner.wire_simple_adder(port, _api2wire_i32(a), _api2wire_i32(b)),
      _wire2api_i32);

  Future<int> primitiveTypes(
          {required int myI32,
          required int myI64,
          required double myF64,
          required bool myBool}) =>
      execute(
          (port) => inner.wire_primitive_types(
              port,
              _api2wire_i32(myI32),
              _api2wire_i64(myI64),
              _api2wire_f64(myF64),
              _api2wire_bool(myBool)),
          _wire2api_i32);

  Future<String> handleString({required String s}) => execute(
      (port) => inner.wire_handle_string(port, _api2wire_String(s)),
      _wire2api_String);

  Future<Uint8List> handleVecU8({required Uint8List v}) => execute(
      (port) => inner.wire_handle_vec_u8(port, _api2wire_uint_8_list(v)),
      _wire2api_uint_8_list);

  Future<Uint8List> handleZeroCopyResult({required int n}) => execute(
      (port) => inner.wire_handle_zero_copy_result(port, _api2wire_i32(n)),
      _wire2api_ZeroCopyBuffer_Uint8List);

  Future<MySize> handleStruct({required MySize arg, required MySize boxed}) =>
      execute(
          (port) => inner.wire_handle_struct(port,
              _api2wire_box_autoadd_my_size(arg), _api2wire_box_my_size(boxed)),
          _wire2api_my_size);

  Future<NewTypeInt> handleNewtype({required NewTypeInt arg}) => execute(
      (port) => inner.wire_handle_newtype(
          port, _api2wire_box_autoadd_new_type_int(arg)),
      _wire2api_new_type_int);

  Future<List<MySize>> handleListOfStruct({required List<MySize> l}) => execute(
      (port) =>
          inner.wire_handle_list_of_struct(port, _api2wire_list_my_size(l)),
      _wire2api_list_my_size);

  Future<MyTreeNode> handleComplexStruct({required MyTreeNode s}) => execute(
      (port) => inner.wire_handle_complex_struct(
          port, _api2wire_box_autoadd_my_tree_node(s)),
      _wire2api_my_tree_node);

  Future<int> returnErr() => execute(
      (port) => inner.wire_return_err(
            port,
          ),
      _wire2api_i32);

  Future<int> returnPanic() => execute(
      (port) => inner.wire_return_panic(
            port,
          ),
      _wire2api_i32);

  // Section: api2wire
  int _api2wire_i32(int raw) {
    return raw;
  }

  int _api2wire_i64(int raw) {
    return raw;
  }

  double _api2wire_f64(double raw) {
    return raw;
  }

  bool _api2wire_bool(bool raw) {
    return raw;
  }

  ffi.Pointer<wire_uint_8_list> _api2wire_String(String raw) {
    return _api2wire_uint_8_list(utf8.encoder.convert(raw));
  }

  ffi.Pointer<wire_uint_8_list> _api2wire_uint_8_list(Uint8List raw) {
    final ans = inner.new_uint_8_list(raw.length);
    ans.ref.ptr.asTypedList(raw.length).setAll(0, raw);
    return ans;
  }

  int _api2wire_u8(int raw) {
    return raw;
  }

  ffi.Pointer<wire_uint_8_list> _api2wire_ZeroCopyBuffer_Uint8List(
      Uint8List raw) {
    return _api2wire_uint_8_list(raw);
  }

  ffi.Pointer<wire_MySize> _api2wire_box_autoadd_my_size(MySize raw) {
    final ptr = inner.new_box_autoadd_my_size();
    _api_fill_to_wire_my_size(raw, ptr.ref);
    return ptr;
  }

  ffi.Pointer<wire_MySize> _api2wire_box_my_size(MySize raw) {
    final ptr = inner.new_box_my_size();
    _api_fill_to_wire_my_size(raw, ptr.ref);
    return ptr;
  }

  ffi.Pointer<wire_NewTypeInt> _api2wire_box_autoadd_new_type_int(
      NewTypeInt raw) {
    final ptr = inner.new_box_autoadd_new_type_int();
    _api_fill_to_wire_new_type_int(raw, ptr.ref);
    return ptr;
  }

  ffi.Pointer<wire_list_my_size> _api2wire_list_my_size(List<MySize> raw) {
    final ans = inner.new_list_my_size(raw.length);
    for (var i = 0; i < raw.length; ++i) {
      _api_fill_to_wire_my_size(raw[i], ans.ref.ptr[i]);
    }
    return ans;
  }

  ffi.Pointer<wire_MyTreeNode> _api2wire_box_autoadd_my_tree_node(
      MyTreeNode raw) {
    final ptr = inner.new_box_autoadd_my_tree_node();
    _api_fill_to_wire_my_tree_node(raw, ptr.ref);
    return ptr;
  }

  ffi.Pointer<wire_list_my_tree_node> _api2wire_list_my_tree_node(
      List<MyTreeNode> raw) {
    final ans = inner.new_list_my_tree_node(raw.length);
    for (var i = 0; i < raw.length; ++i) {
      _api_fill_to_wire_my_tree_node(raw[i], ans.ref.ptr[i]);
    }
    return ans;
  }

  // Section: api_fill_to_wire

  void _api_fill_to_wire_my_size(MySize apiObj, wire_MySize wireObj) {
    wireObj.width = _api2wire_i32(apiObj.width);
    wireObj.height = _api2wire_i32(apiObj.height);
  }

  void _api_fill_to_wire_new_type_int(
      NewTypeInt apiObj, wire_NewTypeInt wireObj) {
    wireObj.field0 = _api2wire_i64(apiObj.field0);
  }

  void _api_fill_to_wire_my_tree_node(
      MyTreeNode apiObj, wire_MyTreeNode wireObj) {
    wireObj.value_i32 = _api2wire_i32(apiObj.valueI32);
    wireObj.value_vec_u8 = _api2wire_uint_8_list(apiObj.valueVecU8);
    wireObj.children = _api2wire_list_my_tree_node(apiObj.children);
  }
}

// Section: wire2api
int _wire2api_i32(dynamic raw) {
  return raw as int;
}

int _wire2api_i64(dynamic raw) {
  return raw as int;
}

double _wire2api_f64(dynamic raw) {
  return raw as double;
}

bool _wire2api_bool(dynamic raw) {
  return raw as bool;
}

String _wire2api_String(dynamic raw) {
  return raw as String;
}

Uint8List _wire2api_uint_8_list(dynamic raw) {
  return raw as Uint8List;
}

int _wire2api_u8(dynamic raw) {
  return raw as int;
}

Uint8List _wire2api_ZeroCopyBuffer_Uint8List(dynamic raw) {
  return raw as Uint8List;
}

MySize _wire2api_my_size(dynamic raw) {
  final arr = raw as List<dynamic>;
  if (arr.length != 2)
    throw Exception('unexpected arr length: expect 2 but see ${arr.length}');
  return MySize(
    width: _wire2api_i32(arr[0]),
    height: _wire2api_i32(arr[1]),
  );
}

NewTypeInt _wire2api_new_type_int(dynamic raw) {
  final arr = raw as List<dynamic>;
  if (arr.length != 1)
    throw Exception('unexpected arr length: expect 1 but see ${arr.length}');
  return NewTypeInt(
    field0: _wire2api_i64(arr[0]),
  );
}

List<MySize> _wire2api_list_my_size(dynamic raw) {
  return (raw as List<dynamic>).map((item) => _wire2api_my_size(item)).toList();
}

MyTreeNode _wire2api_my_tree_node(dynamic raw) {
  final arr = raw as List<dynamic>;
  if (arr.length != 3)
    throw Exception('unexpected arr length: expect 3 but see ${arr.length}');
  return MyTreeNode(
    valueI32: _wire2api_i32(arr[0]),
    valueVecU8: _wire2api_uint_8_list(arr[1]),
    children: _wire2api_list_my_tree_node(arr[2]),
  );
}

List<MyTreeNode> _wire2api_list_my_tree_node(dynamic raw) {
  return (raw as List<dynamic>)
      .map((item) => _wire2api_my_tree_node(item))
      .toList();
}

// ignore_for_file: camel_case_types, non_constant_identifier_names, avoid_positional_boolean_parameters, annotate_overrides

// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.

/// generated by flutter_rust_bridge
class FlutterRustBridgeExampleWire implements FlutterRustBridgeWireBase {
  /// Holds the symbol lookup function.
  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
      _lookup;

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

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

  void wire_simple_adder(
    int port,
    int a,
    int b,
  ) {
    return _wire_simple_adder(
      port,
      a,
      b,
    );
  }

  late final _wire_simple_adderPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(
              ffi.Int64, ffi.Int32, ffi.Int32)>>('wire_simple_adder');
  late final _wire_simple_adder =
      _wire_simple_adderPtr.asFunction<void Function(int, int, int)>();

  void wire_primitive_types(
    int port,
    int my_i32,
    int my_i64,
    double my_f64,
    ffi.Pointer<bool> my_bool,
  ) {
    return _wire_primitive_types(
      port,
      my_i32,
      my_i64,
      my_f64,
      my_bool,
    );
  }

  late final _wire_primitive_typesPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(ffi.Int64, ffi.Int32, ffi.Int64, ffi.Double,
              ffi.Pointer<bool>)>>('wire_primitive_types');
  late final _wire_primitive_types = _wire_primitive_typesPtr
      .asFunction<void Function(int, int, int, double, ffi.Pointer<bool>)>();

  void wire_handle_string(
    int port,
    ffi.Pointer<wire_uint_8_list> s,
  ) {
    return _wire_handle_string(
      port,
      s,
    );
  }

  late final _wire_handle_stringPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(
              ffi.Int64, ffi.Pointer<wire_uint_8_list>)>>('wire_handle_string');
  late final _wire_handle_string = _wire_handle_stringPtr
      .asFunction<void Function(int, ffi.Pointer<wire_uint_8_list>)>();

  void wire_handle_vec_u8(
    int port,
    ffi.Pointer<wire_uint_8_list> v,
  ) {
    return _wire_handle_vec_u8(
      port,
      v,
    );
  }

  late final _wire_handle_vec_u8Ptr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(
              ffi.Int64, ffi.Pointer<wire_uint_8_list>)>>('wire_handle_vec_u8');
  late final _wire_handle_vec_u8 = _wire_handle_vec_u8Ptr
      .asFunction<void Function(int, ffi.Pointer<wire_uint_8_list>)>();

  void wire_handle_zero_copy_result(
    int port,
    int n,
  ) {
    return _wire_handle_zero_copy_result(
      port,
      n,
    );
  }

  late final _wire_handle_zero_copy_resultPtr =
      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64, ffi.Int32)>>(
          'wire_handle_zero_copy_result');
  late final _wire_handle_zero_copy_result =
      _wire_handle_zero_copy_resultPtr.asFunction<void Function(int, int)>();

  void wire_handle_struct(
    int port,
    ffi.Pointer<wire_MySize> arg,
    ffi.Pointer<wire_MySize> boxed,
  ) {
    return _wire_handle_struct(
      port,
      arg,
      boxed,
    );
  }

  late final _wire_handle_structPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(ffi.Int64, ffi.Pointer<wire_MySize>,
              ffi.Pointer<wire_MySize>)>>('wire_handle_struct');
  late final _wire_handle_struct = _wire_handle_structPtr.asFunction<
      void Function(int, ffi.Pointer<wire_MySize>, ffi.Pointer<wire_MySize>)>();

  void wire_handle_newtype(
    int port,
    ffi.Pointer<wire_NewTypeInt> arg,
  ) {
    return _wire_handle_newtype(
      port,
      arg,
    );
  }

  late final _wire_handle_newtypePtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(
              ffi.Int64, ffi.Pointer<wire_NewTypeInt>)>>('wire_handle_newtype');
  late final _wire_handle_newtype = _wire_handle_newtypePtr
      .asFunction<void Function(int, ffi.Pointer<wire_NewTypeInt>)>();

  void wire_handle_list_of_struct(
    int port,
    ffi.Pointer<wire_list_my_size> l,
  ) {
    return _wire_handle_list_of_struct(
      port,
      l,
    );
  }

  late final _wire_handle_list_of_structPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(ffi.Int64,
              ffi.Pointer<wire_list_my_size>)>>('wire_handle_list_of_struct');
  late final _wire_handle_list_of_struct = _wire_handle_list_of_structPtr
      .asFunction<void Function(int, ffi.Pointer<wire_list_my_size>)>();

  void wire_handle_complex_struct(
    int port,
    ffi.Pointer<wire_MyTreeNode> s,
  ) {
    return _wire_handle_complex_struct(
      port,
      s,
    );
  }

  late final _wire_handle_complex_structPtr = _lookup<
      ffi.NativeFunction<
          ffi.Void Function(ffi.Int64,
              ffi.Pointer<wire_MyTreeNode>)>>('wire_handle_complex_struct');
  late final _wire_handle_complex_struct = _wire_handle_complex_structPtr
      .asFunction<void Function(int, ffi.Pointer<wire_MyTreeNode>)>();

  void wire_return_err(
    int port,
  ) {
    return _wire_return_err(
      port,
    );
  }

  late final _wire_return_errPtr =
      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
          'wire_return_err');
  late final _wire_return_err =
      _wire_return_errPtr.asFunction<void Function(int)>();

  void wire_return_panic(
    int port,
  ) {
    return _wire_return_panic(
      port,
    );
  }

  late final _wire_return_panicPtr =
      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
          'wire_return_panic');
  late final _wire_return_panic =
      _wire_return_panicPtr.asFunction<void Function(int)>();

  ffi.Pointer<wire_uint_8_list> new_uint_8_list(
    int len,
  ) {
    return _new_uint_8_list(
      len,
    );
  }

  late final _new_uint_8_listPtr = _lookup<
      ffi.NativeFunction<
          ffi.Pointer<wire_uint_8_list> Function(
              ffi.Int32)>>('new_uint_8_list');
  late final _new_uint_8_list = _new_uint_8_listPtr
      .asFunction<ffi.Pointer<wire_uint_8_list> Function(int)>();

  ffi.Pointer<wire_MySize> new_box_autoadd_my_size() {
    return _new_box_autoadd_my_size();
  }

  late final _new_box_autoadd_my_sizePtr =
      _lookup<ffi.NativeFunction<ffi.Pointer<wire_MySize> Function()>>(
          'new_box_autoadd_my_size');
  late final _new_box_autoadd_my_size = _new_box_autoadd_my_sizePtr
      .asFunction<ffi.Pointer<wire_MySize> Function()>();

  ffi.Pointer<wire_MySize> new_box_my_size() {
    return _new_box_my_size();
  }

  late final _new_box_my_sizePtr =
      _lookup<ffi.NativeFunction<ffi.Pointer<wire_MySize> Function()>>(
          'new_box_my_size');
  late final _new_box_my_size =
      _new_box_my_sizePtr.asFunction<ffi.Pointer<wire_MySize> Function()>();

  ffi.Pointer<wire_NewTypeInt> new_box_autoadd_new_type_int() {
    return _new_box_autoadd_new_type_int();
  }

  late final _new_box_autoadd_new_type_intPtr =
      _lookup<ffi.NativeFunction<ffi.Pointer<wire_NewTypeInt> Function()>>(
          'new_box_autoadd_new_type_int');
  late final _new_box_autoadd_new_type_int = _new_box_autoadd_new_type_intPtr
      .asFunction<ffi.Pointer<wire_NewTypeInt> Function()>();

  ffi.Pointer<wire_list_my_size> new_list_my_size(
    int len,
  ) {
    return _new_list_my_size(
      len,
    );
  }

  late final _new_list_my_sizePtr = _lookup<
      ffi.NativeFunction<
          ffi.Pointer<wire_list_my_size> Function(
              ffi.Int32)>>('new_list_my_size');
  late final _new_list_my_size = _new_list_my_sizePtr
      .asFunction<ffi.Pointer<wire_list_my_size> Function(int)>();

  ffi.Pointer<wire_MyTreeNode> new_box_autoadd_my_tree_node() {
    return _new_box_autoadd_my_tree_node();
  }

  late final _new_box_autoadd_my_tree_nodePtr =
      _lookup<ffi.NativeFunction<ffi.Pointer<wire_MyTreeNode> Function()>>(
          'new_box_autoadd_my_tree_node');
  late final _new_box_autoadd_my_tree_node = _new_box_autoadd_my_tree_nodePtr
      .asFunction<ffi.Pointer<wire_MyTreeNode> Function()>();

  ffi.Pointer<wire_list_my_tree_node> new_list_my_tree_node(
    int len,
  ) {
    return _new_list_my_tree_node(
      len,
    );
  }

  late final _new_list_my_tree_nodePtr = _lookup<
      ffi.NativeFunction<
          ffi.Pointer<wire_list_my_tree_node> Function(
              ffi.Int32)>>('new_list_my_tree_node');
  late final _new_list_my_tree_node = _new_list_my_tree_nodePtr
      .asFunction<ffi.Pointer<wire_list_my_tree_node> Function(int)>();

  void store_dart_post_cobject(
    int ptr,
  ) {
    return _store_dart_post_cobject(
      ptr,
    );
  }

  late final _store_dart_post_cobjectPtr =
      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int32)>>(
          'store_dart_post_cobject');
  late final _store_dart_post_cobject =
      _store_dart_post_cobjectPtr.asFunction<void Function(int)>();
}

class wire_uint_8_list extends ffi.Struct {
  external ffi.Pointer<ffi.Uint8> ptr;

  @ffi.Int32()
  external int len;
}

class wire_MySize extends ffi.Struct {
  @ffi.Int32()
  external int width;

  @ffi.Int32()
  external int height;
}

class wire_NewTypeInt extends ffi.Struct {
  @ffi.Int64()
  external int field0;
}

class wire_list_my_size extends ffi.Struct {
  external ffi.Pointer<wire_MySize> ptr;

  @ffi.Int32()
  external int len;
}

class wire_list_my_tree_node extends ffi.Struct {
  external ffi.Pointer<wire_MyTreeNode> ptr;

  @ffi.Int32()
  external int len;
}

class wire_MyTreeNode extends ffi.Struct {
  @ffi.Int32()
  external int value_i32;

  external ffi.Pointer<wire_uint_8_list> value_vec_u8;

  external ffi.Pointer<wire_list_my_tree_node> children;
}

typedef bool = ffi.NativeFunction<ffi.Int32 Function(ffi.Pointer<ffi.Int32>)>;

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

How did you make that collapsable details tag?

Generated rust code is the same

C output

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct wire_uint_8_list {
  uint8_t *ptr;
  int32_t len;
} wire_uint_8_list;

typedef struct wire_MySize {
  int32_t width;
  int32_t height;
} wire_MySize;

typedef struct wire_NewTypeInt {
  int64_t field0;
} wire_NewTypeInt;

typedef struct wire_list_my_size {
  struct wire_MySize *ptr;
  int32_t len;
} wire_list_my_size;

typedef struct wire_list_my_tree_node {
  struct wire_MyTreeNode *ptr;
  int32_t len;
} wire_list_my_tree_node;

typedef struct wire_MyTreeNode {
  int32_t value_i32;
  struct wire_uint_8_list *value_vec_u8;
  struct wire_list_my_tree_node *children;
} wire_MyTreeNode;

typedef int64_t DartPort;

typedef bool (*DartPostCObjectFnType)(DartPort port_id, void *message);

void wire_simple_adder(int64_t port, int32_t a, int32_t b);

void wire_primitive_types(int64_t port,
                          int32_t my_i32,
                          int64_t my_i64,
                          double my_f64,
                          bool my_bool);

void wire_handle_string(int64_t port, struct wire_uint_8_list *s);

void wire_handle_vec_u8(int64_t port, struct wire_uint_8_list *v);

void wire_handle_zero_copy_result(int64_t port, int32_t n);

void wire_handle_struct(int64_t port, struct wire_MySize *arg, struct wire_MySize *boxed);

void wire_handle_newtype(int64_t port, struct wire_NewTypeInt *arg);

void wire_handle_list_of_struct(int64_t port, struct wire_list_my_size *l);

void wire_handle_complex_struct(int64_t port, struct wire_MyTreeNode *s);

void wire_return_err(int64_t port);

void wire_return_panic(int64_t port);

struct wire_uint_8_list *new_uint_8_list(int32_t len);

struct wire_MySize *new_box_autoadd_my_size(void);

struct wire_MySize *new_box_my_size(void);

struct wire_NewTypeInt *new_box_autoadd_new_type_int(void);

struct wire_list_my_size *new_list_my_size(int32_t len);

struct wire_MyTreeNode *new_box_autoadd_my_tree_node(void);

struct wire_list_my_tree_node *new_list_my_tree_node(int32_t len);

void store_dart_post_cobject(DartPostCObjectFnType ptr);

Debug log
debug.log

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

How did you make that collapsable details tag?

<details>
sth
</details>

by the way I have add: 7e5b194

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

you need to have a newline between < details > and the ```

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

Well, cbindgen (rust->c) seems good. Maybe a bug in ffigen(c->dart)? could you plz print its version

notice that all these has nothing related to this lib indeed ;) what my lib generates is those wrappers against raw c pointers and types

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

ffigen 4.0.0

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

oops wait a bit

[2021-10-11T00:46:53Z DEBUG flutter_rust_bridge_codegen::commands] command output: Output { status: ExitStatus(ExitStatus(0)), stdout: "Running in Directory: '/home/greg/p/chess/flutter_rust_bridge/frb_example/pure_dart'\nInput Headers: [/tmp/tmp.c]\n[SEVERE] : Header /tmp/tmp.c: Total errors/warnings: 1.\n[SEVERE] : /tmp/tmp.c:1:10: fatal error: 'stdarg.h' file not found [Lexical or Preprocessor Issue]\nFinished, Bindings generated in /tmp/.tmpo4DjsV\n", stderr: "" }

log clearly indicates this problem

'stdarg.h' file not found

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

Wait... that's slightly old (4.1.0 exists), let me try updating that

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

conclusion: maybe this is the problem 'stdarg.h' file not found. you can run ffigen by yourself and reproduce it. my code does nothing but simply run a command using Rust's Command. So should be same if you do that in your shell.

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

Hmm, ok...

4.1.0 doesn't change anything by the way.

stdarg.h does exist... /usr/lib/gcc/x86_64-unknown-linux-gnu/10.2/include/stdarg.h, will see if I can figure out why it's not finding it.

Actually this is probably the right instance of stedarg.h, anyways a lot of copies of it exist: /usr/lib/clang/12.0.1/include/stdarg.h

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

let me add some logs, such that you can easily reproduce it in a shell by yourself.

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

I think I can reproduce this, the command I need is in the logs

 execute command: "dart" "pub" "global" "run" "ffigen" "--config" "/tmp/.tmp9vqMVW"

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

yes. but that temp file (config) will be deleted after run imho.

my new commit: 3ff8340 prints out whole config. so you can copy and paste.

maybe use that new commit, and reproduce it in your shell, and see.

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

Awesome, thanks

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

You are welcome!

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

btw you may create an issue in ffigen if it still errors.

@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

It is still erroring, I may end up doing that, but want to see if I can debug it first (even if I can debug it, I may end up doing that...)

dart-lang/native#389 is similar, but I can actually build the .c file into a .o with clang, so it's not the case here that clang can't find the header at all...

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

Hmm then I cannot help you much, since I am not an expert in ffigen.

But if you find the solution and need me to change code in this repo, feel free to ask!

@fzyzcjy fzyzcjy changed the title codegen produces dart code with incorrect types, including on examples. codegen produces dart code with incorrect types, including on examples - caused by external tool ffigen fail to find headers Oct 11, 2021
@gmorenz
Copy link
Author

gmorenz commented Oct 11, 2021

Heh, so I can get it it find stdarg.h, by cd-ing to / first. Not sure why, but it's using relative paths for the clang include directories (per strace). Changing to / before running flutter_rust_bridge_codegen makes the output look right too.

It's been a long day for me today, so I'm going to put this down for the night and figure out how to fix it properly tomorrow (and open issues in the relevant places then). I'm pretty sure this is purely a ffigen (or even libclang) issue, so you could close this out for now, or leave it open and I'll close it out once the issue is fully resolved.

Thanks for all your help and super prompt response!

@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 11, 2021

You are welcome! Happy to hear that you find out something towards the solution!

Just leave this issue open, and we can close it after everything is finished.

@fzyzcjy fzyzcjy changed the title codegen produces dart code with incorrect types, including on examples - caused by external tool ffigen fail to find headers codegen produces dart code with incorrect types, including on examples - caused by external tool ffigen fail to find stdarg.h headers Oct 22, 2021
@fzyzcjy
Copy link
Owner

fzyzcjy commented Oct 22, 2021

Seems to be same issue: dart-lang/native#417

@fzyzcjy fzyzcjy reopened this Oct 22, 2021
fzyzcjy added a commit that referenced this issue Oct 23, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Nov 2, 2021

Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now. If you find this problem please file a new issue. All system setups can be slightly different so it's always better to open new issues and reference the related ones. Thanks for your contribution.

@github-actions github-actions bot closed this as completed Nov 2, 2021
@github-actions
Copy link
Contributor

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 16, 2021
Czappi pushed a commit to Czappi/flutter_rust_bridge that referenced this issue Nov 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants