[ffigen] Support for array parameters in functions, array workarounds in Structs (#18)

- Added multi-dimension array support in Struct using array-workaround config flag.
- Added support for arrays parameters in functions.
diff --git a/pkgs/ffigen/example/libclang-example/generated_bindings.dart b/pkgs/ffigen/example/libclang-example/generated_bindings.dart
index 8f19852..4fbfac3 100644
--- a/pkgs/ffigen/example/libclang-example/generated_bindings.dart
+++ b/pkgs/ffigen/example/libclang-example/generated_bindings.dart
@@ -71,17 +71,44 @@
   ffi.Pointer<ffi.Void> _data_item_1;
   ffi.Pointer<ffi.Void> _data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXCursor_data get data => _ArrayHelper_CXCursor_data(this, 3);
+  /// Helper for array `data`.
+  ArrayHelper_CXCursor_data_level0 get data =>
+      ArrayHelper_CXCursor_data_level0(this, [3], 0, 0);
 }
 
-/// Helper for array data in struct CXCursor
-class _ArrayHelper_CXCursor_data {
+/// Helper for array `data` in struct `CXCursor`.
+class ArrayHelper_CXCursor_data_level0 {
   final CXCursor _struct;
-  final int length;
-  _ArrayHelper_CXCursor_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXCursor_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._data_item_0 = value;
         break;
@@ -92,35 +119,9 @@
         _struct._data_item_2 = value;
         break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._data_item_0;
-      case 1:
-        return _struct._data_item_1;
-      case 2:
-        return _struct._data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 class CXCursorAndRangeVisitor extends ffi.Struct {
@@ -152,18 +153,44 @@
   @ffi.Uint64()
   int _data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXFileUniqueID_data get data =>
-      _ArrayHelper_CXFileUniqueID_data(this, 3);
+  /// Helper for array `data`.
+  ArrayHelper_CXFileUniqueID_data_level0 get data =>
+      ArrayHelper_CXFileUniqueID_data_level0(this, [3], 0, 0);
 }
 
-/// Helper for array data in struct CXFileUniqueID
-class _ArrayHelper_CXFileUniqueID_data {
+/// Helper for array `data` in struct `CXFileUniqueID`.
+class ArrayHelper_CXFileUniqueID_data_level0 {
   final CXFileUniqueID _struct;
-  final int length;
-  _ArrayHelper_CXFileUniqueID_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXFileUniqueID_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  int operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, int value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._data_item_0 = value;
         break;
@@ -174,35 +201,9 @@
         _struct._data_item_2 = value;
         break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  int operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._data_item_0;
-      case 1:
-        return _struct._data_item_1;
-      case 2:
-        return _struct._data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 class CXGlobalOptFlags {
@@ -262,61 +263,55 @@
 class CXIdxLoc extends ffi.Struct {
   ffi.Pointer<ffi.Void> _ptr_data_item_0;
   ffi.Pointer<ffi.Void> _ptr_data_item_1;
-  ffi.Pointer<ffi.Void> _ptr_data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXIdxLoc_ptr_data get ptr_data =>
-      _ArrayHelper_CXIdxLoc_ptr_data(this, 3);
+  /// Helper for array `ptr_data`.
+  ArrayHelper_CXIdxLoc_ptr_data_level0 get ptr_data =>
+      ArrayHelper_CXIdxLoc_ptr_data_level0(this, [2], 0, 0);
   @ffi.Uint32()
   int int_data;
 }
 
-/// Helper for array ptr_data in struct CXIdxLoc
-class _ArrayHelper_CXIdxLoc_ptr_data {
+/// Helper for array `ptr_data` in struct `CXIdxLoc`.
+class ArrayHelper_CXIdxLoc_ptr_data_level0 {
   final CXIdxLoc _struct;
-  final int length;
-  _ArrayHelper_CXIdxLoc_ptr_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXIdxLoc_ptr_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._ptr_data_item_0 = value;
         break;
       case 1:
         _struct._ptr_data_item_1 = value;
         break;
-      case 2:
-        _struct._ptr_data_item_2 = value;
-        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._ptr_data_item_0;
-      case 1:
-        return _struct._ptr_data_item_1;
-      case 2:
-        return _struct._ptr_data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 class CXIdxObjCCategoryDeclInfo extends ffi.Struct {}
@@ -372,61 +367,55 @@
 class CXSourceLocation extends ffi.Struct {
   ffi.Pointer<ffi.Void> _ptr_data_item_0;
   ffi.Pointer<ffi.Void> _ptr_data_item_1;
-  ffi.Pointer<ffi.Void> _ptr_data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXSourceLocation_ptr_data get ptr_data =>
-      _ArrayHelper_CXSourceLocation_ptr_data(this, 3);
+  /// Helper for array `ptr_data`.
+  ArrayHelper_CXSourceLocation_ptr_data_level0 get ptr_data =>
+      ArrayHelper_CXSourceLocation_ptr_data_level0(this, [2], 0, 0);
   @ffi.Uint32()
   int int_data;
 }
 
-/// Helper for array ptr_data in struct CXSourceLocation
-class _ArrayHelper_CXSourceLocation_ptr_data {
+/// Helper for array `ptr_data` in struct `CXSourceLocation`.
+class ArrayHelper_CXSourceLocation_ptr_data_level0 {
   final CXSourceLocation _struct;
-  final int length;
-  _ArrayHelper_CXSourceLocation_ptr_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXSourceLocation_ptr_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._ptr_data_item_0 = value;
         break;
       case 1:
         _struct._ptr_data_item_1 = value;
         break;
-      case 2:
-        _struct._ptr_data_item_2 = value;
-        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._ptr_data_item_0;
-      case 1:
-        return _struct._ptr_data_item_1;
-      case 2:
-        return _struct._ptr_data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 /// Identifies a half-open character range in the source code.
@@ -436,11 +425,10 @@
 class CXSourceRange extends ffi.Struct {
   ffi.Pointer<ffi.Void> _ptr_data_item_0;
   ffi.Pointer<ffi.Void> _ptr_data_item_1;
-  ffi.Pointer<ffi.Void> _ptr_data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXSourceRange_ptr_data get ptr_data =>
-      _ArrayHelper_CXSourceRange_ptr_data(this, 3);
+  /// Helper for array `ptr_data`.
+  ArrayHelper_CXSourceRange_ptr_data_level0 get ptr_data =>
+      ArrayHelper_CXSourceRange_ptr_data_level0(this, [2], 0, 0);
   @ffi.Uint32()
   int begin_int_data;
 
@@ -448,52 +436,47 @@
   int end_int_data;
 }
 
-/// Helper for array ptr_data in struct CXSourceRange
-class _ArrayHelper_CXSourceRange_ptr_data {
+/// Helper for array `ptr_data` in struct `CXSourceRange`.
+class ArrayHelper_CXSourceRange_ptr_data_level0 {
   final CXSourceRange _struct;
-  final int length;
-  _ArrayHelper_CXSourceRange_ptr_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXSourceRange_ptr_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._ptr_data_item_0 = value;
         break;
       case 1:
         _struct._ptr_data_item_1 = value;
         break;
-      case 2:
-        _struct._ptr_data_item_2 = value;
-        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._ptr_data_item_0;
-      case 1:
-        return _struct._ptr_data_item_1;
-      case 2:
-        return _struct._ptr_data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 /// Identifies an array of ranges.
@@ -554,20 +537,50 @@
   int _int_data_item_1;
   @ffi.Uint32()
   int _int_data_item_2;
+  @ffi.Uint32()
+  int _int_data_item_3;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXToken_int_data get int_data =>
-      _ArrayHelper_CXToken_int_data(this, 3);
+  /// Helper for array `int_data`.
+  ArrayHelper_CXToken_int_data_level0 get int_data =>
+      ArrayHelper_CXToken_int_data_level0(this, [4], 0, 0);
   ffi.Pointer<ffi.Void> ptr_data;
 }
 
-/// Helper for array int_data in struct CXToken
-class _ArrayHelper_CXToken_int_data {
+/// Helper for array `int_data` in struct `CXToken`.
+class ArrayHelper_CXToken_int_data_level0 {
   final CXToken _struct;
-  final int length;
-  _ArrayHelper_CXToken_int_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXToken_int_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  int operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._int_data_item_0;
+      case 1:
+        return _struct._int_data_item_1;
+      case 2:
+        return _struct._int_data_item_2;
+      case 3:
+        return _struct._int_data_item_3;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, int value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._int_data_item_0 = value;
         break;
@@ -577,36 +590,13 @@
       case 2:
         _struct._int_data_item_2 = value;
         break;
+      case 3:
+        _struct._int_data_item_3 = value;
+        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  int operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._int_data_item_0;
-      case 1:
-        return _struct._int_data_item_1;
-      case 2:
-        return _struct._int_data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 class CXTranslationUnitImpl extends ffi.Struct {}
@@ -618,58 +608,53 @@
 
   ffi.Pointer<ffi.Void> _data_item_0;
   ffi.Pointer<ffi.Void> _data_item_1;
-  ffi.Pointer<ffi.Void> _data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXType_data get data => _ArrayHelper_CXType_data(this, 3);
+  /// Helper for array `data`.
+  ArrayHelper_CXType_data_level0 get data =>
+      ArrayHelper_CXType_data_level0(this, [2], 0, 0);
 }
 
-/// Helper for array data in struct CXType
-class _ArrayHelper_CXType_data {
+/// Helper for array `data` in struct `CXType`.
+class ArrayHelper_CXType_data_level0 {
   final CXType _struct;
-  final int length;
-  _ArrayHelper_CXType_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXType_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._data_item_0 = value;
         break;
       case 1:
         _struct._data_item_1 = value;
         break;
-      case 2:
-        _struct._data_item_2 = value;
-        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._data_item_0;
-      case 1:
-        return _struct._data_item_1;
-      case 2:
-        return _struct._data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 /// Describes the kind of type
@@ -2572,6 +2557,7 @@
 
 typedef _dart_clang_enableStackTraces = void Function();
 
+/// Returns non-zero if the ranges are the same, zero if they differ.
 int clang_equalRanges_wrap(
   ffi.Pointer<CXSourceRange> c1,
   ffi.Pointer<CXSourceRange> c2,
diff --git a/pkgs/ffigen/example/libclang-example/pubspec.yaml b/pkgs/ffigen/example/libclang-example/pubspec.yaml
index d4dc2fd..832f111 100644
--- a/pkgs/ffigen/example/libclang-example/pubspec.yaml
+++ b/pkgs/ffigen/example/libclang-example/pubspec.yaml
@@ -59,5 +59,8 @@
     unsigned long long: 8
     enum: 4
 
-  # Doc Comments for generated binings: Can be full, brief(default) or none
+  # False by default.
+  array-workaround: true
+
+  # Doc Comments for generated binings: Can be full, brief(default) or none.
   comments: full
diff --git a/pkgs/ffigen/lib/src/code_generator/struc.dart b/pkgs/ffigen/lib/src/code_generator/struc.dart
index 4cb5152..5e2db56 100644
--- a/pkgs/ffigen/lib/src/code_generator/struc.dart
+++ b/pkgs/ffigen/lib/src/code_generator/struc.dart
@@ -43,6 +43,16 @@
   })  : members = members ?? [],
         super(name: name, dartDoc: dartDoc);
 
+  List<int> _getArrayDimensionLengths(Type type) {
+    final array = <int>[];
+    var startType = type;
+    while (startType.broadType == BroadType.ConstantArray) {
+      array.add(startType.length);
+      startType = startType.child;
+    }
+    return array;
+  }
+
   @override
   BindingString toBindingString(Writer w) {
     final s = StringBuffer();
@@ -61,9 +71,9 @@
       if (m.type.broadType == BroadType.ConstantArray) {
         // TODO(5): Remove array helpers when inline array support arives.
         final arrayHelper = ArrayHelper(
-          helperClassName: '_ArrayHelper_${name}_${m.name}',
-          elementType: m.type.elementType,
-          length: 3,
+          helperClassGroupName: 'ArrayHelper_${name}_${m.name}',
+          elementType: m.type.getBaseArrayType(),
+          dimensions: _getArrayDimensionLengths(m.type),
           name: m.name,
           structName: name,
           elementNamePrefix: '_${m.name}_item_',
@@ -104,19 +114,30 @@
 // Helper bindings for struct array.
 class ArrayHelper {
   final Type elementType;
-  final int length;
+  final List<int> dimensions;
   final String structName;
 
   final String name;
-  final String helperClassName;
+  final String helperClassGroupName;
   final String elementNamePrefix;
 
+  int _expandedArrayLength;
+  int get expandedArrayLength {
+    if (_expandedArrayLength != null) return _expandedArrayLength;
+
+    int arrayLength = 1;
+    for (final i in dimensions) {
+      arrayLength = arrayLength * i;
+    }
+    return arrayLength;
+  }
+
   ArrayHelper({
     @required this.elementType,
-    @required this.length,
+    @required this.dimensions,
     @required this.structName,
     @required this.name,
-    @required this.helperClassName,
+    @required this.helperClassGroupName,
     @required this.elementNamePrefix,
   });
 
@@ -126,76 +147,100 @@
     final arrayDartType = elementType.getDartType(w);
     final arrayCType = elementType.getCType(w);
 
-    for (var i = 0; i < length; i++) {
+    for (int i = 0; i < expandedArrayLength; i++) {
       if (elementType.isPrimitive) {
         s.write('  @${arrayCType}()\n');
       }
       s.write('  ${arrayDartType} ${elementNamePrefix}$i;\n');
     }
 
-    s.write('/// helper for array, supports `[]` operator\n');
+    s.write('/// Helper for array `$name`.\n');
     s.write(
-        '$helperClassName get $name => ${helperClassName}(this, $length);\n');
+        '${helperClassGroupName}_level0 get $name => ${helperClassGroupName}_level0(this, $dimensions, 0, 0);\n');
 
     return s.toString();
   }
 
-  /// Creates an array helper binding for struct array.
   String helperClassString(Writer w) {
     final s = StringBuffer();
-
     final arrayType = elementType.getDartType(w);
+    for (int dim = 0; dim < dimensions.length; dim++) {
+      final helperClassName = '${helperClassGroupName}_level${dim}';
+      final structIdentifier = '_struct';
+      final dimensionsIdentifier = 'dimensions';
+      final levelIdentifier = 'level';
+      final absoluteIndexIdentifier = '_absoluteIndex';
+      final checkBoundsFunctionIdentifier = '_checkBounds';
+      final legthIdentifier = 'length';
 
-    s.write('/// Helper for array $name in struct $structName\n');
+      s.write('/// Helper for array `$name` in struct `$structName`.\n');
 
-    // Write class declaration.
-    s.write('class $helperClassName{\n');
-    s.write('final $structName _struct;\n');
-    s.write('final int length;\n');
-    s.write('$helperClassName(this._struct, this.length);\n');
+      // Write class declaration.
+      s.write('class ${helperClassName}{\n');
+      s.write('final $structName $structIdentifier;\n');
+      s.write('final List<int> $dimensionsIdentifier;\n');
+      s.write('final int $levelIdentifier;\n');
+      s.write('final int $absoluteIndexIdentifier;\n');
+      s.write(
+          'int get $legthIdentifier => $dimensionsIdentifier[$levelIdentifier];\n');
 
-    // Override []= operator.
-    s.write('void operator []=(int index, $arrayType value) {\n');
-    s.write('switch(index) {\n');
-    for (var i = 0; i < length; i++) {
-      s.write('case $i:\n');
-      s.write('  _struct.${elementNamePrefix}$i = value;\n');
-      s.write('  break;\n');
+      // Write class constructor.
+      s.write(
+          '$helperClassName(this.$structIdentifier, this.$dimensionsIdentifier, this.$levelIdentifier, this.$absoluteIndexIdentifier);\n');
+
+      // Write checkBoundsFunction.
+      s.write('''
+  void $checkBoundsFunctionIdentifier(int index) {
+    if (index >= $legthIdentifier || index < 0) {
+      throw RangeError('Dimension \$$levelIdentifier: index not in range 0..\${$legthIdentifier} exclusive.');
     }
-    s.write('default:\n');
-    s.write(
-        "  throw RangeError('Index \$index must be in the range [0..${length - 1}].');");
-    s.write('}\n');
-    s.write('}\n');
-
-    // Override [] operator.
-    s.write('$arrayType operator [](int index) {\n');
-    s.write('switch(index) {\n');
-    for (var i = 0; i < length; i++) {
-      s.write('case $i:\n');
-      s.write('  return _struct.${elementNamePrefix}$i;\n');
+  }
+  ''');
+      // If this isn't the last level.
+      if (dim + 1 != dimensions.length) {
+        // Override [] operator.
+        s.write('''
+  ${helperClassGroupName}_level${dim + 1} operator [](int index) {
+    $checkBoundsFunctionIdentifier(index);
+    int offset = index;
+    for (int i = level + 1; i < $dimensionsIdentifier.length; i++) {
+      offset *= $dimensionsIdentifier[i];
     }
-    s.write('default:\n');
-    s.write(
-        "  throw RangeError('Index \$index must be in the range [0..${length - 1}].');");
-    s.write('}\n');
-    s.write('}\n');
+    return ${helperClassGroupName}_level${dim + 1}(
+        $structIdentifier, $dimensionsIdentifier, $levelIdentifier + 1, $absoluteIndexIdentifier + offset);
+  }
+''');
+      } else {
+        // This is the last level, add switching logic here.
+        // Override [] operator.
+        s.write('$arrayType operator[](int index){\n');
+        s.write('$checkBoundsFunctionIdentifier(index);\n');
+        s.write('switch($absoluteIndexIdentifier+index){\n');
+        for (int i = 0; i < expandedArrayLength; i++) {
+          s.write('case $i:\n');
+          s.write('  return $structIdentifier.${elementNamePrefix}$i;\n');
+        }
+        s.write('default:\n');
+        s.write("  throw Exception('Invalid Array Helper generated.');");
+        s.write('}\n');
+        s.write('}\n');
 
-    // Override toString().
-    s.write('@override\n');
-    s.write('String toString() {\n');
-    s.write("if (length == 0) return '[]';\n");
-    s.write("final sb = StringBuffer('[');\n");
-    s.write('sb.write(this[0]);\n');
-    s.write('for (var i = 1; i < length; i++) {\n');
-    s.write("  sb.write(',');\n");
-    s.write('  sb.write(this[i]);');
-    s.write('}\n');
-    s.write("sb.write(']');");
-    s.write('return sb.toString();\n');
-    s.write('}\n');
-
-    s.write('}\n\n');
+        // Override []= operator.
+        s.write('void operator[]=(int index, $arrayType value){\n');
+        s.write('$checkBoundsFunctionIdentifier(index);\n');
+        s.write('switch($absoluteIndexIdentifier+index){\n');
+        for (int i = 0; i < expandedArrayLength; i++) {
+          s.write('case $i:\n');
+          s.write('  $structIdentifier.${elementNamePrefix}$i = value;\n');
+          s.write('  break;\n');
+        }
+        s.write('default:\n');
+        s.write("  throw Exception('Invalid Array Helper generated.');\n");
+        s.write('}\n');
+        s.write('}\n');
+      }
+      s.write('}\n');
+    }
     return s.toString();
   }
 }
diff --git a/pkgs/ffigen/lib/src/code_generator/type.dart b/pkgs/ffigen/lib/src/code_generator/type.dart
index b393d34..dccdec3 100644
--- a/pkgs/ffigen/lib/src/code_generator/type.dart
+++ b/pkgs/ffigen/lib/src/code_generator/type.dart
@@ -38,6 +38,7 @@
 
   /// Stores its element type in NativeType as only those are supported.
   ConstantArray,
+  IncompleteArray,
 
   /// Used as a marker, so that functions/structs having these can exclude them.
   Unimplemented,
@@ -73,12 +74,11 @@
   /// The BroadType of this Type.
   final BroadType broadType;
 
-  /// Child Type, e.g Pointer(Parent) to Int(Child).
+  /// Child Type, e.g Pointer(Parent) to Int(Child), or Child Type of an Array.
   final Type child;
 
-  /// For ConstantArray type.
-  final int arrayLength;
-  final Type elementType;
+  /// For ConstantArray and IncompleteArray type.
+  final int length;
 
   /// For storing cursor type info for an unimplemented type.
   String unimplementedReason;
@@ -89,8 +89,7 @@
     this.structName,
     this.nativeType,
     this.nativeFuncName,
-    this.arrayLength,
-    this.elementType,
+    this.length,
     this.unimplementedReason,
   });
 
@@ -107,8 +106,18 @@
   factory Type.nativeType(SupportedNativeType nativeType) {
     return Type._(broadType: BroadType.NativeType, nativeType: nativeType);
   }
-  factory Type.constantArray(int arrayLength, Type elementType) {
-    return Type._(broadType: BroadType.ConstantArray, elementType: elementType);
+  factory Type.constantArray(int length, Type elementType) {
+    return Type._(
+      broadType: BroadType.ConstantArray,
+      child: elementType,
+      length: length,
+    );
+  }
+  factory Type.incompleteArray(Type elementType) {
+    return Type._(
+      broadType: BroadType.ConstantArray,
+      child: elementType,
+    );
   }
   factory Type.unimplemented(String reason) {
     return Type._(
@@ -117,15 +126,28 @@
 
   /// Get base broad type for any type.
   ///
-  /// E.g int** has base Broadtype as NativeType.
+  /// E.g int** has base Broadtype as NativeType,
+  /// double[2][3] has base broadtype as double.
   BroadType getBaseBroadType() {
-    if (broadType == BroadType.Pointer) {
+    if (child != null) {
       return child.getBaseBroadType();
     } else {
       return broadType;
     }
   }
 
+  /// Get base Array type.
+  ///
+  /// Returns itself if it's not an Array Type.
+  Type getBaseArrayType() {
+    if (broadType == BroadType.ConstantArray ||
+        broadType == BroadType.IncompleteArray) {
+      return child.getBaseArrayType();
+    } else {
+      return this;
+    }
+  }
+
   bool get isPrimitive => broadType == BroadType.NativeType;
 
   String getCType(Writer w) {
@@ -138,6 +160,12 @@
         return structName;
       case BroadType.NativeFunction:
         return '${w.ffiLibraryPrefix}.NativeFunction<${nativeFuncName}>';
+      case BroadType
+          .IncompleteArray: // Array parameters are treated as Pointers in C.
+        return '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>';
+      case BroadType
+          .ConstantArray: // Array parameters are treated as Pointers in C.
+        return '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>';
       default:
         throw Exception('cType unknown');
     }
@@ -153,6 +181,12 @@
         return structName;
       case BroadType.NativeFunction:
         return '${w.ffiLibraryPrefix}.NativeFunction<${nativeFuncName}>';
+      case BroadType
+          .IncompleteArray: // Array parameters are treated as Pointers in C.
+        return '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>';
+      case BroadType
+          .ConstantArray: // Array parameters are treated as Pointers in C.
+        return '${w.ffiLibraryPrefix}.Pointer<${child.getCType(w)}>';
       default:
         throw Exception('dart type unknown for ${broadType.toString()}');
     }
diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart
index 49cda0c..fbd2ae6 100644
--- a/pkgs/ffigen/lib/src/config_provider/config.dart
+++ b/pkgs/ffigen/lib/src/config_provider/config.dart
@@ -62,6 +62,11 @@
   /// Extracted Doc comment type.
   String comment;
 
+  /// If tool should generate array workarounds.
+  ///
+  /// If false(default), structs with inline array members will have all its members removed.
+  bool arrayWorkaround;
+
   /// Manually creating configurations.
   ///
   /// Use [Config.fromYaml] if extracting info from a yaml file.
@@ -251,6 +256,15 @@
         defaultValue: strings.brief,
         extractedResult: (dynamic result) => comment = result as String,
       ),
+      strings.arrayWorkaround: Specification<bool>(
+        description:
+            'whether or not to generate workarounds for inline arrays in structures',
+        isRequired: false,
+        validator: booleanValidator,
+        extractor: booleanExtractor,
+        defaultValue: false,
+        extractedResult: (dynamic result) => arrayWorkaround = result as bool,
+      ),
     };
   }
 }
diff --git a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
index 1cf40a3..546c8dc 100644
--- a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
+++ b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
@@ -39,17 +39,44 @@
   ffi.Pointer<ffi.Void> _data_item_1;
   ffi.Pointer<ffi.Void> _data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXCursor_data get data => _ArrayHelper_CXCursor_data(this, 3);
+  /// Helper for array `data`.
+  ArrayHelper_CXCursor_data_level0 get data =>
+      ArrayHelper_CXCursor_data_level0(this, [3], 0, 0);
 }
 
-/// Helper for array data in struct CXCursor
-class _ArrayHelper_CXCursor_data {
+/// Helper for array `data` in struct `CXCursor`.
+class ArrayHelper_CXCursor_data_level0 {
   final CXCursor _struct;
-  final int length;
-  _ArrayHelper_CXCursor_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXCursor_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._data_item_0 = value;
         break;
@@ -60,35 +87,9 @@
         _struct._data_item_2 = value;
         break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._data_item_0;
-      case 1:
-        return _struct._data_item_1;
-      case 2:
-        return _struct._data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 /// Describes the kind of entity that a cursor refers to.
@@ -770,72 +771,65 @@
 class CXSourceLocation extends ffi.Struct {
   ffi.Pointer<ffi.Void> _ptr_data_item_0;
   ffi.Pointer<ffi.Void> _ptr_data_item_1;
-  ffi.Pointer<ffi.Void> _ptr_data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXSourceLocation_ptr_data get ptr_data =>
-      _ArrayHelper_CXSourceLocation_ptr_data(this, 3);
+  /// Helper for array `ptr_data`.
+  ArrayHelper_CXSourceLocation_ptr_data_level0 get ptr_data =>
+      ArrayHelper_CXSourceLocation_ptr_data_level0(this, [2], 0, 0);
   @ffi.Uint32()
   int int_data;
 }
 
-/// Helper for array ptr_data in struct CXSourceLocation
-class _ArrayHelper_CXSourceLocation_ptr_data {
+/// Helper for array `ptr_data` in struct `CXSourceLocation`.
+class ArrayHelper_CXSourceLocation_ptr_data_level0 {
   final CXSourceLocation _struct;
-  final int length;
-  _ArrayHelper_CXSourceLocation_ptr_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXSourceLocation_ptr_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._ptr_data_item_0 = value;
         break;
       case 1:
         _struct._ptr_data_item_1 = value;
         break;
-      case 2:
-        _struct._ptr_data_item_2 = value;
-        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._ptr_data_item_0;
-      case 1:
-        return _struct._ptr_data_item_1;
-      case 2:
-        return _struct._ptr_data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 /// Identifies a half-open character range in the source code.
 class CXSourceRange extends ffi.Struct {
   ffi.Pointer<ffi.Void> _ptr_data_item_0;
   ffi.Pointer<ffi.Void> _ptr_data_item_1;
-  ffi.Pointer<ffi.Void> _ptr_data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXSourceRange_ptr_data get ptr_data =>
-      _ArrayHelper_CXSourceRange_ptr_data(this, 3);
+  /// Helper for array `ptr_data`.
+  ArrayHelper_CXSourceRange_ptr_data_level0 get ptr_data =>
+      ArrayHelper_CXSourceRange_ptr_data_level0(this, [2], 0, 0);
   @ffi.Uint32()
   int begin_int_data;
 
@@ -843,52 +837,47 @@
   int end_int_data;
 }
 
-/// Helper for array ptr_data in struct CXSourceRange
-class _ArrayHelper_CXSourceRange_ptr_data {
+/// Helper for array `ptr_data` in struct `CXSourceRange`.
+class ArrayHelper_CXSourceRange_ptr_data_level0 {
   final CXSourceRange _struct;
-  final int length;
-  _ArrayHelper_CXSourceRange_ptr_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXSourceRange_ptr_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._ptr_data_item_0;
+      case 1:
+        return _struct._ptr_data_item_1;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._ptr_data_item_0 = value;
         break;
       case 1:
         _struct._ptr_data_item_1 = value;
         break;
-      case 2:
-        _struct._ptr_data_item_2 = value;
-        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._ptr_data_item_0;
-      case 1:
-        return _struct._ptr_data_item_1;
-      case 2:
-        return _struct._ptr_data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 /// A character string.
@@ -972,58 +961,53 @@
 
   ffi.Pointer<ffi.Void> _data_item_0;
   ffi.Pointer<ffi.Void> _data_item_1;
-  ffi.Pointer<ffi.Void> _data_item_2;
 
-  /// helper for array, supports `[]` operator
-  _ArrayHelper_CXType_data get data => _ArrayHelper_CXType_data(this, 3);
+  /// Helper for array `data`.
+  ArrayHelper_CXType_data_level0 get data =>
+      ArrayHelper_CXType_data_level0(this, [2], 0, 0);
 }
 
-/// Helper for array data in struct CXType
-class _ArrayHelper_CXType_data {
+/// Helper for array `data` in struct `CXType`.
+class ArrayHelper_CXType_data_level0 {
   final CXType _struct;
-  final int length;
-  _ArrayHelper_CXType_data(this._struct, this.length);
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_CXType_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ffi.Pointer<ffi.Void> operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
   void operator []=(int index, ffi.Pointer<ffi.Void> value) {
-    switch (index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
       case 0:
         _struct._data_item_0 = value;
         break;
       case 1:
         _struct._data_item_1 = value;
         break;
-      case 2:
-        _struct._data_item_2 = value;
-        break;
       default:
-        throw RangeError('Index $index must be in the range [0..2].');
+        throw Exception('Invalid Array Helper generated.');
     }
   }
-
-  ffi.Pointer<ffi.Void> operator [](int index) {
-    switch (index) {
-      case 0:
-        return _struct._data_item_0;
-      case 1:
-        return _struct._data_item_1;
-      case 2:
-        return _struct._data_item_2;
-      default:
-        throw RangeError('Index $index must be in the range [0..2].');
-    }
-  }
-
-  @override
-  String toString() {
-    if (length == 0) return '[]';
-    final sb = StringBuffer('[');
-    sb.write(this[0]);
-    for (var i = 1; i < length; i++) {
-      sb.write(',');
-      sb.write(this[i]);
-    }
-    sb.write(']');
-    return sb.toString();
-  }
 }
 
 /// Describes the kind of type
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
index 62803f6..3afb7b7 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
@@ -21,7 +21,6 @@
   _func = null;
   structByValueParameter = false;
   unimplementedParameterType = false;
-  constantArrayParameterType = false;
 
   final name = cursor.spelling();
   if (shouldIncludeFunc(name)) {
@@ -39,14 +38,6 @@
       return null; // Returning null so that [addToBindings] function excludes this.
     }
 
-    if (constantArrayParameterType) {
-      _logger.fine(
-          '---- Removed Function, reason: constant array passed to function parameter: ${cursor.completeStringRepr()}');
-      _logger.warning(
-          "Skipped Function '$name', constant array in function parameter not supported.");
-      return null; // Returning null so that [addToBindings] function excludes this.
-    }
-
     if (rt.getBaseBroadType() == BroadType.Unimplemented ||
         unimplementedParameterType) {
       _logger.fine(
@@ -68,7 +59,6 @@
 }
 
 bool structByValueParameter = false;
-bool constantArrayParameterType = false;
 bool unimplementedParameterType = false;
 Type _getFunctionReturnType(Pointer<clang.CXCursor> cursor) {
   return cursor.returnType().toCodeGenTypeAndDispose();
@@ -87,8 +77,6 @@
     //TODO(3): Remove this when support for Structs by value arrives.
     if (pt.broadType == BroadType.Struct) {
       structByValueParameter = true;
-    } else if (pt.broadType == BroadType.ConstantArray) {
-      constantArrayParameterType = true;
     } else if (pt.getBaseBroadType() == BroadType.Unimplemented) {
       unimplementedParameterType = true;
     }
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/structdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/structdecl_parser.dart
index 0c9dfa3..d7c9dc4 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/structdecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/structdecl_parser.dart
@@ -8,6 +8,7 @@
 import 'package:logging/logging.dart';
 
 import '../clang_bindings/clang_bindings.dart' as clang;
+import '../data.dart';
 import '../includer.dart';
 import '../utils.dart';
 
@@ -53,6 +54,7 @@
 List<Member> _members;
 List<Member> _getMembers(Pointer<clang.CXCursor> cursor, String structName) {
   _members = [];
+  arrayMember = false;
   nestedStructMember = false;
   unimplementedMemberType = false;
 
@@ -65,7 +67,13 @@
   visitChildrenResultChecker(resultCode);
 
   // Returning null to exclude the struct members as it has a struct by value field.
-  if (nestedStructMember) {
+  if (arrayMember && !config.arrayWorkaround) {
+    _logger.fine(
+        '---- Removed Struct members, reason: struct has array members ${cursor.completeStringRepr()}');
+    _logger.warning(
+        'Removed All Struct Members from: $structName, Array members not supported');
+    return null;
+  } else if (nestedStructMember) {
     _logger.fine(
         '---- Removed Struct members, reason: struct has struct members ${cursor.completeStringRepr()}');
     _logger.warning(
@@ -84,6 +92,7 @@
 
 bool nestedStructMember = false;
 bool unimplementedMemberType = false;
+bool arrayMember = false;
 
 /// Visitor for the struct cursor [CXCursorKind.CXCursor_StructDecl].
 ///
@@ -98,11 +107,14 @@
 
       //TODO(4): Remove these when support for Structs by value arrives.
       if (mt.broadType == BroadType.Struct) {
-        // Setting this flag will exclude adding members for this struct's bindings.
+        // Setting this flag will exclude adding members for this struct's
+        // bindings.
         nestedStructMember = true;
       } else if (mt.broadType == BroadType.ConstantArray) {
-        if (mt.elementType.broadType == BroadType.Struct) {
-          // Setting this flag will exclude adding members for this struct's bindings.
+        arrayMember = true;
+        if (mt.child.broadType == BroadType.Struct) {
+          // Setting this flag will exclude adding members for this struct's
+          // bindings.
           nestedStructMember = true;
         }
       }
diff --git a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart
index db37487..9584cea 100644
--- a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart
+++ b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart
@@ -66,6 +66,11 @@
         clang.clang_getNumElements_wrap(cxtype),
         clang.clang_getArrayElementType_wrap(cxtype).toCodeGenTypeAndDispose(),
       );
+    case clang.CXTypeKind
+        .CXType_IncompleteArray: // Primarily used for incomplete array in function parameters.
+      return Type.incompleteArray(
+        clang.clang_getArrayElementType_wrap(cxtype).toCodeGenTypeAndDispose(),
+      );
     default:
       if (cxTypeKindToSupportedNativeTypes.containsKey(kind)) {
         return Type.nativeType(
diff --git a/pkgs/ffigen/lib/src/header_parser/utils.dart b/pkgs/ffigen/lib/src/header_parser/utils.dart
index fbc4d31..c5b7f5f 100644
--- a/pkgs/ffigen/lib/src/header_parser/utils.dart
+++ b/pkgs/ffigen/lib/src/header_parser/utils.dart
@@ -129,7 +129,7 @@
 /// Returns a cursor's associated comment.
 ///
 /// The given string is wrapped at line width = 80 - [indent]. The [indent] is
-/// [commentPrefix.length] by default because a comment starts with
+/// [commentPrefix.dimensions] by default because a comment starts with
 /// [commentPrefix].
 String getCursorDocComment(Pointer<clang.CXCursor> cursor,
     [int indent = commentPrefix.length]) {
diff --git a/pkgs/ffigen/lib/src/strings.dart b/pkgs/ffigen/lib/src/strings.dart
index e96ddc1..a03aa97 100644
--- a/pkgs/ffigen/lib/src/strings.dart
+++ b/pkgs/ffigen/lib/src/strings.dart
@@ -58,6 +58,7 @@
 const sort = 'sort';
 const useSupportedTypedefs = 'use-supported-typedefs';
 const warnWhenRemoving = 'warn-when-removing';
+const arrayWorkaround = 'array-workaround';
 
 const comments = 'comments';
 // Comment type.
diff --git a/pkgs/ffigen/test/native_functions_test/native_functions_bindings.dart b/pkgs/ffigen/test/native_functions_test/native_functions_bindings.dart
deleted file mode 100644
index a9eb1e9..0000000
--- a/pkgs/ffigen/test/native_functions_test/native_functions_bindings.dart
+++ /dev/null
@@ -1,226 +0,0 @@
-/// AUTO GENERATED FILE, DO NOT EDIT.
-///
-/// Generated by `package:ffigen`.
-import 'dart:ffi' as ffi;
-
-/// Holds the Dynamic library.
-ffi.DynamicLibrary _dylib;
-
-/// Initialises the Dynamic library.
-void init(ffi.DynamicLibrary dylib) {
-  _dylib = dylib;
-}
-
-double Function1Double(
-  double x,
-) {
-  return _Function1Double(
-    x,
-  );
-}
-
-final _dart_Function1Double _Function1Double =
-    _dylib.lookupFunction<_c_Function1Double, _dart_Function1Double>(
-        'Function1Double');
-
-typedef _c_Function1Double = ffi.Double Function(
-  ffi.Double x,
-);
-
-typedef _dart_Function1Double = double Function(
-  double x,
-);
-
-double Function1Float(
-  double x,
-) {
-  return _Function1Float(
-    x,
-  );
-}
-
-final _dart_Function1Float _Function1Float = _dylib
-    .lookupFunction<_c_Function1Float, _dart_Function1Float>('Function1Float');
-
-typedef _c_Function1Float = ffi.Float Function(
-  ffi.Float x,
-);
-
-typedef _dart_Function1Float = double Function(
-  double x,
-);
-
-int Function1Int16(
-  int x,
-) {
-  return _Function1Int16(
-    x,
-  );
-}
-
-final _dart_Function1Int16 _Function1Int16 = _dylib
-    .lookupFunction<_c_Function1Int16, _dart_Function1Int16>('Function1Int16');
-
-typedef _c_Function1Int16 = ffi.Int16 Function(
-  ffi.Int16 x,
-);
-
-typedef _dart_Function1Int16 = int Function(
-  int x,
-);
-
-int Function1Int32(
-  int x,
-) {
-  return _Function1Int32(
-    x,
-  );
-}
-
-final _dart_Function1Int32 _Function1Int32 = _dylib
-    .lookupFunction<_c_Function1Int32, _dart_Function1Int32>('Function1Int32');
-
-typedef _c_Function1Int32 = ffi.Int32 Function(
-  ffi.Int32 x,
-);
-
-typedef _dart_Function1Int32 = int Function(
-  int x,
-);
-
-int Function1Int64(
-  int x,
-) {
-  return _Function1Int64(
-    x,
-  );
-}
-
-final _dart_Function1Int64 _Function1Int64 = _dylib
-    .lookupFunction<_c_Function1Int64, _dart_Function1Int64>('Function1Int64');
-
-typedef _c_Function1Int64 = ffi.Int64 Function(
-  ffi.Int64 x,
-);
-
-typedef _dart_Function1Int64 = int Function(
-  int x,
-);
-
-int Function1Int8(
-  int x,
-) {
-  return _Function1Int8(
-    x,
-  );
-}
-
-final _dart_Function1Int8 _Function1Int8 = _dylib
-    .lookupFunction<_c_Function1Int8, _dart_Function1Int8>('Function1Int8');
-
-typedef _c_Function1Int8 = ffi.Int8 Function(
-  ffi.Int8 x,
-);
-
-typedef _dart_Function1Int8 = int Function(
-  int x,
-);
-
-int Function1IntPtr(
-  int x,
-) {
-  return _Function1IntPtr(
-    x,
-  );
-}
-
-final _dart_Function1IntPtr _Function1IntPtr =
-    _dylib.lookupFunction<_c_Function1IntPtr, _dart_Function1IntPtr>(
-        'Function1IntPtr');
-
-typedef _c_Function1IntPtr = ffi.IntPtr Function(
-  ffi.IntPtr x,
-);
-
-typedef _dart_Function1IntPtr = int Function(
-  int x,
-);
-
-int Function1Uint16(
-  int x,
-) {
-  return _Function1Uint16(
-    x,
-  );
-}
-
-final _dart_Function1Uint16 _Function1Uint16 =
-    _dylib.lookupFunction<_c_Function1Uint16, _dart_Function1Uint16>(
-        'Function1Uint16');
-
-typedef _c_Function1Uint16 = ffi.Uint16 Function(
-  ffi.Uint16 x,
-);
-
-typedef _dart_Function1Uint16 = int Function(
-  int x,
-);
-
-int Function1Uint32(
-  int x,
-) {
-  return _Function1Uint32(
-    x,
-  );
-}
-
-final _dart_Function1Uint32 _Function1Uint32 =
-    _dylib.lookupFunction<_c_Function1Uint32, _dart_Function1Uint32>(
-        'Function1Uint32');
-
-typedef _c_Function1Uint32 = ffi.Uint32 Function(
-  ffi.Uint32 x,
-);
-
-typedef _dart_Function1Uint32 = int Function(
-  int x,
-);
-
-int Function1Uint64(
-  int x,
-) {
-  return _Function1Uint64(
-    x,
-  );
-}
-
-final _dart_Function1Uint64 _Function1Uint64 =
-    _dylib.lookupFunction<_c_Function1Uint64, _dart_Function1Uint64>(
-        'Function1Uint64');
-
-typedef _c_Function1Uint64 = ffi.Uint64 Function(
-  ffi.Uint64 x,
-);
-
-typedef _dart_Function1Uint64 = int Function(
-  int x,
-);
-
-int Function1Uint8(
-  int x,
-) {
-  return _Function1Uint8(
-    x,
-  );
-}
-
-final _dart_Function1Uint8 _Function1Uint8 = _dylib
-    .lookupFunction<_c_Function1Uint8, _dart_Function1Uint8>('Function1Uint8');
-
-typedef _c_Function1Uint8 = ffi.Uint8 Function(
-  ffi.Uint8 x,
-);
-
-typedef _dart_Function1Uint8 = int Function(
-  int x,
-);
diff --git a/pkgs/ffigen/test/native_functions_test/native_functions_test.dart b/pkgs/ffigen/test/native_functions_test/native_functions_test.dart
deleted file mode 100644
index b63fc35..0000000
--- a/pkgs/ffigen/test/native_functions_test/native_functions_test.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:ffi';
-import 'dart:io';
-import 'dart:math';
-
-import 'package:test/test.dart';
-import 'native_functions_bindings.dart' as bindings;
-
-void main() {
-  group('Tests for native functions', () {
-    setUpAll(() {
-      var dylibName = 'test/native_functions_test/native_functions.so';
-      if (Platform.isMacOS) {
-        dylibName = 'test/native_functions_test/native_functions.dylib';
-      } else if (Platform.isWindows) {
-        dylibName = r'test\native_functions_test\native_functions.dll';
-      }
-      bindings.init(DynamicLibrary.open(dylibName));
-    });
-    test('uint8_t', () {
-      expect(bindings.Function1Uint8(pow(2, 8).toInt()), 42);
-    });
-    test('uint16_t', () {
-      expect(bindings.Function1Uint16(pow(2, 16).toInt()), 42);
-    });
-    test('uint32_t', () {
-      expect(bindings.Function1Uint32(pow(2, 32).toInt()), 42);
-    });
-    test('uint64_t', () {
-      expect(bindings.Function1Uint64(pow(2, 64).toInt()), 42);
-    });
-    test('int8_t', () {
-      expect(
-          bindings.Function1Int8(pow(2, 7).toInt()), -pow(2, 7).toInt() + 42);
-    });
-    test('int16_t', () {
-      expect(bindings.Function1Int16(pow(2, 15).toInt()),
-          -pow(2, 15).toInt() + 42);
-    });
-    test('int32_t', () {
-      expect(bindings.Function1Int32(pow(2, 31).toInt()),
-          -pow(2, 31).toInt() + 42);
-    });
-    test('int64_t', () {
-      expect(bindings.Function1Int64(pow(2, 63).toInt()),
-          -pow(2, 63).toInt() + 42);
-    });
-    test('intptr_t', () {
-      expect(bindings.Function1IntPtr(0), 42);
-    });
-    test('float', () {
-      expect(bindings.Function1Float(0), 42.0);
-    });
-    test('double', () {
-      expect(bindings.Function1Double(0), 42.0);
-    });
-  });
-}
diff --git a/pkgs/ffigen/test/native_functions_test/build_test_dylib.dart b/pkgs/ffigen/test/native_test/build_test_dylib.dart
similarity index 83%
rename from pkgs/ffigen/test/native_functions_test/build_test_dylib.dart
rename to pkgs/ffigen/test/native_test/build_test_dylib.dart
index 25258f0..2fd2c49 100644
--- a/pkgs/ffigen/test/native_functions_test/build_test_dylib.dart
+++ b/pkgs/ffigen/test/native_test/build_test_dylib.dart
@@ -10,17 +10,17 @@
 ///
 /// Linux:
 /// ```
-/// clang -shared -fpic native_functions.c -o native_functions.so
+/// clang -shared -fpic native_test.c -o native_test.so
 /// ```
 /// MacOS:
 /// ```
-/// clang -shared -fpic native_functions.c -o native_functions.dylib
+/// clang -shared -fpic native_test.c -o native_test.dylib
 /// ```
 /// Windows:
 /// ```
-/// call clang -shared native_functions.c -o native_functions.dll -Wl,"/DEF:native_functions.def"
-/// del native_functions.exp
-/// del native_functions.lib
+/// call clang -shared native_test.c -o native_test.dll -Wl,"/DEF:native_test.def"
+/// del native_test.exp
+/// del native_test.lib
 /// ```
 /// =======================================================================
 /// =======================================================================
@@ -36,21 +36,21 @@
 
 Map<String, Options> platformOptions = {
   LINUX: Options(
-    outputfilename: 'native_functions.so',
+    outputfilename: 'native_test.so',
     sharedFlag: '-shared',
-    inputHeader: 'native_functions.c',
+    inputHeader: 'native_test.c',
     fPIC: '-fpic',
   ),
   WINDOWS: Options(
-    outputfilename: 'native_functions.dll',
+    outputfilename: 'native_test.dll',
     sharedFlag: '-shared',
-    inputHeader: 'native_functions.c',
-    moduleDefPath: '-Wl,/DEF:native_functions.def',
+    inputHeader: 'native_test.c',
+    moduleDefPath: '-Wl,/DEF:native_test.def',
   ),
   MACOS: Options(
-    outputfilename: 'native_functions.dylib',
+    outputfilename: 'native_test.dylib',
     sharedFlag: '-shared',
-    inputHeader: 'native_functions.c',
+    inputHeader: 'native_test.c',
     fPIC: '-fpic',
   ),
 };
diff --git a/pkgs/ffigen/test/native_functions_test/config.yaml b/pkgs/ffigen/test/native_test/config.yaml
similarity index 82%
rename from pkgs/ffigen/test/native_functions_test/config.yaml
rename to pkgs/ffigen/test/native_test/config.yaml
index 3635c70..a25821a 100644
--- a/pkgs/ffigen/test/native_functions_test/config.yaml
+++ b/pkgs/ffigen/test/native_test/config.yaml
@@ -6,11 +6,12 @@
 #    dart ../../bin/ffigen.dart --config config.yaml
 # ===============================================================
 
-output: 'native_functions_bindings.dart'
+output: 'native_test_bindings.dart'
 libclang-dylib-folder: '../../tool/wrapped_libclang'
 sort: true
 headers:
-  - 'native_functions.c'
+  - 'native_test.c'
 header-filter:
   include:
-    - 'native_functions.c'
+    - 'native_test.c'
+array-workaround: true
diff --git a/pkgs/ffigen/test/native_functions_test/native_functions.c b/pkgs/ffigen/test/native_test/native_test.c
similarity index 67%
rename from pkgs/ffigen/test/native_functions_test/native_functions.c
rename to pkgs/ffigen/test/native_test/native_test.c
index 544357e..21c2f16 100644
--- a/pkgs/ffigen/test/native_functions_test/native_functions.c
+++ b/pkgs/ffigen/test/native_test/native_test.c
@@ -1,8 +1,10 @@
 // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+#define aloc(T) ((T *)malloc(sizeof(T)))
 
 #include <stdint.h>
+#include <stdlib.h>
 
 uint8_t Function1Uint8(uint8_t x) { return x + 42; }
 
@@ -25,3 +27,22 @@
 float Function1Float(float x) { return x + 42.0f; }
 
 double Function1Double(double x) { return x + 42.0; }
+
+struct Struct1
+{
+    int8_t a;
+    int32_t data[3][1][2];
+};
+
+struct Struct1 *getStruct1()
+{
+    struct Struct1 *s = aloc(struct Struct1);
+    s->a = 0;
+    s->data[0][0][0] = 1;
+    s->data[0][0][1] = 2;
+    s->data[1][0][0] = 3;
+    s->data[1][0][1] = 4;
+    s->data[2][0][0] = 5;
+    s->data[2][0][1] = 6;
+    return s;
+}
diff --git a/pkgs/ffigen/test/native_test/native_test.dart b/pkgs/ffigen/test/native_test/native_test.dart
new file mode 100644
index 0000000..cc4fa22
--- /dev/null
+++ b/pkgs/ffigen/test/native_test/native_test.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:math';
+
+import 'package:test/test.dart';
+import 'native_test_bindings.dart' as bindings;
+
+void main() {
+  group('Tests for native functions', () {
+    setUpAll(() {
+      var dylibName = 'test/native_test/native_test.so';
+      if (Platform.isMacOS) {
+        dylibName = 'test/native_test/native_test.dylib';
+      } else if (Platform.isWindows) {
+        dylibName = r'test\native_test\native_test.dll';
+      }
+      bindings.init(DynamicLibrary.open(dylibName));
+    });
+    test('uint8_t', () {
+      expect(bindings.Function1Uint8(pow(2, 8).toInt()), 42);
+    });
+    test('uint16_t', () {
+      expect(bindings.Function1Uint16(pow(2, 16).toInt()), 42);
+    });
+    test('uint32_t', () {
+      expect(bindings.Function1Uint32(pow(2, 32).toInt()), 42);
+    });
+    test('uint64_t', () {
+      expect(bindings.Function1Uint64(pow(2, 64).toInt()), 42);
+    });
+    test('int8_t', () {
+      expect(
+          bindings.Function1Int8(pow(2, 7).toInt()), -pow(2, 7).toInt() + 42);
+    });
+    test('int16_t', () {
+      expect(bindings.Function1Int16(pow(2, 15).toInt()),
+          -pow(2, 15).toInt() + 42);
+    });
+    test('int32_t', () {
+      expect(bindings.Function1Int32(pow(2, 31).toInt()),
+          -pow(2, 31).toInt() + 42);
+    });
+    test('int64_t', () {
+      expect(bindings.Function1Int64(pow(2, 63).toInt()),
+          -pow(2, 63).toInt() + 42);
+    });
+    test('intptr_t', () {
+      expect(bindings.Function1IntPtr(0), 42);
+    });
+    test('float', () {
+      expect(bindings.Function1Float(0), 42.0);
+    });
+    test('double', () {
+      expect(bindings.Function1Double(0), 42.0);
+    });
+    test('array-workaround: Order of access', () {
+      final struct1 = bindings.getStruct1();
+      int expectedValue = 1;
+      for (int i = 0; i < struct1.ref.data.dimensions[0]; i++) {
+        for (int j = 0; j < struct1.ref.data.dimensions[1]; j++) {
+          for (int k = 0; k < struct1.ref.data.dimensions[2]; k++) {
+            expect(struct1.ref.data[i][j][k], expectedValue);
+            expectedValue++;
+          }
+        }
+      }
+    });
+    test('array-workaround: Range Errors', () {
+      final struct1 = bindings.getStruct1();
+      // Index (get) above range.
+      expect(
+          () => struct1.ref.data[4][0][0], throwsA(TypeMatcher<RangeError>()));
+      expect(
+          () => struct1.ref.data[0][2][0], throwsA(TypeMatcher<RangeError>()));
+      expect(
+          () => struct1.ref.data[0][0][3], throwsA(TypeMatcher<RangeError>()));
+      // Index (get) below range.
+      expect(
+          () => struct1.ref.data[-1][0][0], throwsA(TypeMatcher<RangeError>()));
+      expect(
+          () => struct1.ref.data[-1][0][0], throwsA(TypeMatcher<RangeError>()));
+      expect(
+          () => struct1.ref.data[0][0][-1], throwsA(TypeMatcher<RangeError>()));
+
+      // Index (set) above range.
+      expect(() => struct1.ref.data[4][0][0] = 0,
+          throwsA(TypeMatcher<RangeError>()));
+      expect(() => struct1.ref.data[0][2][0] = 0,
+          throwsA(TypeMatcher<RangeError>()));
+      expect(() => struct1.ref.data[0][0][3] = 0,
+          throwsA(TypeMatcher<RangeError>()));
+      // Index (get) below range.
+      expect(() => struct1.ref.data[-1][0][0] = 0,
+          throwsA(TypeMatcher<RangeError>()));
+      expect(() => struct1.ref.data[-1][0][0] = 0,
+          throwsA(TypeMatcher<RangeError>()));
+      expect(() => struct1.ref.data[0][0][-1] = 0,
+          throwsA(TypeMatcher<RangeError>()));
+    });
+  });
+}
diff --git a/pkgs/ffigen/test/native_functions_test/native_functions.def b/pkgs/ffigen/test/native_test/native_test.def
similarity index 100%
rename from pkgs/ffigen/test/native_functions_test/native_functions.def
rename to pkgs/ffigen/test/native_test/native_test.def
diff --git a/pkgs/ffigen/test/native_test/native_test_bindings.dart b/pkgs/ffigen/test/native_test/native_test_bindings.dart
new file mode 100644
index 0000000..a9c5309
--- /dev/null
+++ b/pkgs/ffigen/test/native_test/native_test_bindings.dart
@@ -0,0 +1,376 @@
+/// AUTO GENERATED FILE, DO NOT EDIT.
+///
+/// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Holds the Dynamic library.
+ffi.DynamicLibrary _dylib;
+
+/// Initialises the Dynamic library.
+void init(ffi.DynamicLibrary dylib) {
+  _dylib = dylib;
+}
+
+double Function1Double(
+  double x,
+) {
+  return _Function1Double(
+    x,
+  );
+}
+
+final _dart_Function1Double _Function1Double =
+    _dylib.lookupFunction<_c_Function1Double, _dart_Function1Double>(
+        'Function1Double');
+
+typedef _c_Function1Double = ffi.Double Function(
+  ffi.Double x,
+);
+
+typedef _dart_Function1Double = double Function(
+  double x,
+);
+
+double Function1Float(
+  double x,
+) {
+  return _Function1Float(
+    x,
+  );
+}
+
+final _dart_Function1Float _Function1Float = _dylib
+    .lookupFunction<_c_Function1Float, _dart_Function1Float>('Function1Float');
+
+typedef _c_Function1Float = ffi.Float Function(
+  ffi.Float x,
+);
+
+typedef _dart_Function1Float = double Function(
+  double x,
+);
+
+int Function1Int16(
+  int x,
+) {
+  return _Function1Int16(
+    x,
+  );
+}
+
+final _dart_Function1Int16 _Function1Int16 = _dylib
+    .lookupFunction<_c_Function1Int16, _dart_Function1Int16>('Function1Int16');
+
+typedef _c_Function1Int16 = ffi.Int16 Function(
+  ffi.Int16 x,
+);
+
+typedef _dart_Function1Int16 = int Function(
+  int x,
+);
+
+int Function1Int32(
+  int x,
+) {
+  return _Function1Int32(
+    x,
+  );
+}
+
+final _dart_Function1Int32 _Function1Int32 = _dylib
+    .lookupFunction<_c_Function1Int32, _dart_Function1Int32>('Function1Int32');
+
+typedef _c_Function1Int32 = ffi.Int32 Function(
+  ffi.Int32 x,
+);
+
+typedef _dart_Function1Int32 = int Function(
+  int x,
+);
+
+int Function1Int64(
+  int x,
+) {
+  return _Function1Int64(
+    x,
+  );
+}
+
+final _dart_Function1Int64 _Function1Int64 = _dylib
+    .lookupFunction<_c_Function1Int64, _dart_Function1Int64>('Function1Int64');
+
+typedef _c_Function1Int64 = ffi.Int64 Function(
+  ffi.Int64 x,
+);
+
+typedef _dart_Function1Int64 = int Function(
+  int x,
+);
+
+int Function1Int8(
+  int x,
+) {
+  return _Function1Int8(
+    x,
+  );
+}
+
+final _dart_Function1Int8 _Function1Int8 = _dylib
+    .lookupFunction<_c_Function1Int8, _dart_Function1Int8>('Function1Int8');
+
+typedef _c_Function1Int8 = ffi.Int8 Function(
+  ffi.Int8 x,
+);
+
+typedef _dart_Function1Int8 = int Function(
+  int x,
+);
+
+int Function1IntPtr(
+  int x,
+) {
+  return _Function1IntPtr(
+    x,
+  );
+}
+
+final _dart_Function1IntPtr _Function1IntPtr =
+    _dylib.lookupFunction<_c_Function1IntPtr, _dart_Function1IntPtr>(
+        'Function1IntPtr');
+
+typedef _c_Function1IntPtr = ffi.IntPtr Function(
+  ffi.IntPtr x,
+);
+
+typedef _dart_Function1IntPtr = int Function(
+  int x,
+);
+
+int Function1Uint16(
+  int x,
+) {
+  return _Function1Uint16(
+    x,
+  );
+}
+
+final _dart_Function1Uint16 _Function1Uint16 =
+    _dylib.lookupFunction<_c_Function1Uint16, _dart_Function1Uint16>(
+        'Function1Uint16');
+
+typedef _c_Function1Uint16 = ffi.Uint16 Function(
+  ffi.Uint16 x,
+);
+
+typedef _dart_Function1Uint16 = int Function(
+  int x,
+);
+
+int Function1Uint32(
+  int x,
+) {
+  return _Function1Uint32(
+    x,
+  );
+}
+
+final _dart_Function1Uint32 _Function1Uint32 =
+    _dylib.lookupFunction<_c_Function1Uint32, _dart_Function1Uint32>(
+        'Function1Uint32');
+
+typedef _c_Function1Uint32 = ffi.Uint32 Function(
+  ffi.Uint32 x,
+);
+
+typedef _dart_Function1Uint32 = int Function(
+  int x,
+);
+
+int Function1Uint64(
+  int x,
+) {
+  return _Function1Uint64(
+    x,
+  );
+}
+
+final _dart_Function1Uint64 _Function1Uint64 =
+    _dylib.lookupFunction<_c_Function1Uint64, _dart_Function1Uint64>(
+        'Function1Uint64');
+
+typedef _c_Function1Uint64 = ffi.Uint64 Function(
+  ffi.Uint64 x,
+);
+
+typedef _dart_Function1Uint64 = int Function(
+  int x,
+);
+
+int Function1Uint8(
+  int x,
+) {
+  return _Function1Uint8(
+    x,
+  );
+}
+
+final _dart_Function1Uint8 _Function1Uint8 = _dylib
+    .lookupFunction<_c_Function1Uint8, _dart_Function1Uint8>('Function1Uint8');
+
+typedef _c_Function1Uint8 = ffi.Uint8 Function(
+  ffi.Uint8 x,
+);
+
+typedef _dart_Function1Uint8 = int Function(
+  int x,
+);
+
+class Struct1 extends ffi.Struct {
+  @ffi.Int8()
+  int a;
+
+  @ffi.Int32()
+  int _data_item_0;
+  @ffi.Int32()
+  int _data_item_1;
+  @ffi.Int32()
+  int _data_item_2;
+  @ffi.Int32()
+  int _data_item_3;
+  @ffi.Int32()
+  int _data_item_4;
+  @ffi.Int32()
+  int _data_item_5;
+
+  /// Helper for array `data`.
+  ArrayHelper_Struct1_data_level0 get data =>
+      ArrayHelper_Struct1_data_level0(this, [3, 1, 2], 0, 0);
+}
+
+/// Helper for array `data` in struct `Struct1`.
+class ArrayHelper_Struct1_data_level0 {
+  final Struct1 _struct;
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_Struct1_data_level0(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ArrayHelper_Struct1_data_level1 operator [](int index) {
+    _checkBounds(index);
+    int offset = index;
+    for (int i = level + 1; i < dimensions.length; i++) {
+      offset *= dimensions[i];
+    }
+    return ArrayHelper_Struct1_data_level1(
+        _struct, dimensions, level + 1, _absoluteIndex + offset);
+  }
+}
+
+/// Helper for array `data` in struct `Struct1`.
+class ArrayHelper_Struct1_data_level1 {
+  final Struct1 _struct;
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_Struct1_data_level1(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  ArrayHelper_Struct1_data_level2 operator [](int index) {
+    _checkBounds(index);
+    int offset = index;
+    for (int i = level + 1; i < dimensions.length; i++) {
+      offset *= dimensions[i];
+    }
+    return ArrayHelper_Struct1_data_level2(
+        _struct, dimensions, level + 1, _absoluteIndex + offset);
+  }
+}
+
+/// Helper for array `data` in struct `Struct1`.
+class ArrayHelper_Struct1_data_level2 {
+  final Struct1 _struct;
+  final List<int> dimensions;
+  final int level;
+  final int _absoluteIndex;
+  int get length => dimensions[level];
+  ArrayHelper_Struct1_data_level2(
+      this._struct, this.dimensions, this.level, this._absoluteIndex);
+  void _checkBounds(int index) {
+    if (index >= length || index < 0) {
+      throw RangeError(
+          'Dimension $level: index not in range 0..${length} exclusive.');
+    }
+  }
+
+  int operator [](int index) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        return _struct._data_item_0;
+      case 1:
+        return _struct._data_item_1;
+      case 2:
+        return _struct._data_item_2;
+      case 3:
+        return _struct._data_item_3;
+      case 4:
+        return _struct._data_item_4;
+      case 5:
+        return _struct._data_item_5;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+
+  void operator []=(int index, int value) {
+    _checkBounds(index);
+    switch (_absoluteIndex + index) {
+      case 0:
+        _struct._data_item_0 = value;
+        break;
+      case 1:
+        _struct._data_item_1 = value;
+        break;
+      case 2:
+        _struct._data_item_2 = value;
+        break;
+      case 3:
+        _struct._data_item_3 = value;
+        break;
+      case 4:
+        _struct._data_item_4 = value;
+        break;
+      case 5:
+        _struct._data_item_5 = value;
+        break;
+      default:
+        throw Exception('Invalid Array Helper generated.');
+    }
+  }
+}
+
+ffi.Pointer<Struct1> getStruct1() {
+  return _getStruct1();
+}
+
+final _dart_getStruct1 _getStruct1 =
+    _dylib.lookupFunction<_c_getStruct1, _dart_getStruct1>('getStruct1');
+
+typedef _c_getStruct1 = ffi.Pointer<Struct1> Function();
+
+typedef _dart_getStruct1 = ffi.Pointer<Struct1> Function();
diff --git a/pkgs/ffigen/tool/libclang_config.yaml b/pkgs/ffigen/tool/libclang_config.yaml
index 3fe9bb2..9401a00 100644
--- a/pkgs/ffigen/tool/libclang_config.yaml
+++ b/pkgs/ffigen/tool/libclang_config.yaml
@@ -21,6 +21,8 @@
     - Index.h
     - CXString.h
 
+array-workaround: true
+
 enums:
   include:
     names: