Skip to content

Commit

Permalink
Support array fields
Browse files Browse the repository at this point in the history
  • Loading branch information
simolus3 committed Dec 14, 2023
1 parent b9d738c commit 01e7752
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 7 deletions.
2 changes: 2 additions & 0 deletions pkgs/ffigen/example/ffinative/headers/example.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ float *divide(int a, int b);
/** Divides 2 floats, returns a pointer to double. */
double *dividePrecision(float a, float b);

const int array[10];

/** Version of the native C library */
const char* const library_version = "1.0.0-native";
4 changes: 4 additions & 0 deletions pkgs/ffigen/example/ffinative/lib/generated_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ external ffi.Pointer<ffi.Double> dividePrecision(
double b,
);

@ffi.Array(10)
@ffi.Native<ffi.Array<ffi.Int>>()
external ffi.Array<ffi.Int> array;

/// Version of the native C library
@ffi.Native<ffi.Pointer<ffi.Char>>()
external final ffi.Pointer<ffi.Char> library_version;
Expand Down
23 changes: 23 additions & 0 deletions pkgs/ffigen/lib/src/code_generator/global.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '../config_provider/config_types.dart';
import 'binding.dart';
import 'binding_string.dart';
import 'compound.dart';
import 'pointer.dart';
import 'type.dart';
import 'utils.dart';
import 'writer.dart';
Expand Down Expand Up @@ -48,6 +49,10 @@ class Global extends LookUpBinding {
final cType = type.getCType(w);

if (nativeConfig.enabled) {
if (type case final ConstantArray arr) {
arr.generateSizeAnnotation(s, w);
}

s
..write('@${w.ffiLibraryPrefix}.Native<')
..write(cType)
Expand Down Expand Up @@ -106,3 +111,21 @@ class Global extends LookUpBinding {
type.addDependencies(dependencies);
}
}

extension on ConstantArray {
void generateSizeAnnotation(StringBuffer buffer, Writer w) {
buffer.write('@${w.ffiLibraryPrefix}.Array(');

Type? array = this;
var first = true;
while (array is ConstantArray) {
if (!first) buffer.write(', ');

buffer.write(array.length);
first = false;
array = array.baseArrayType;
}

buffer.writeln(')');
}
}
13 changes: 12 additions & 1 deletion pkgs/ffigen/lib/src/code_generator/pointer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ class PointerType extends Type {
/// Represents a constant array, which has a fixed size.
class ConstantArray extends PointerType {
final int length;
ConstantArray(this.length, Type child) : super._(child);
final bool useArrayType;

ConstantArray(this.length, this.useArrayType, Type child) : super._(child);

@override
Type get baseArrayType => child.baseArrayType;
Expand All @@ -58,6 +60,15 @@ class ConstantArray extends PointerType {

@override
String cacheKey() => '${child.cacheKey()}[$length]';

@override
String getCType(Writer w) {
if (useArrayType) {
return '${w.ffiLibraryPrefix}.Array<${child.getCType(w)}>';
}

return super.getCType(w);
}
}

/// Represents an incomplete array, which has an unknown size.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ Global? parseVarDeclaration(clang_types.CXCursor cursor) {
_logger.fine('++++ Adding Global: ${cursor.completeStringRepr()}');

final cType = cursor.type();
final type = cType.toCodeGenType();

final type = cType.toCodeGenType(
// Native fields can be arrays, but if we use the lookup based method of
// reading fields there's no way to turn a Pointer into an array.
supportNonInlineArray: config.ffiNativeConfig.enabled);
if (type.baseType is UnimplementedType) {
_logger.fine('---- Removed Global, reason: unsupported type: '
'${cursor.completeStringRepr()}');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Type getCodeGenType(
/// Cursor of the declaration, currently this is useful only to extract
/// parameter names in function types.
clang_types.CXCursor? originalCursor,
bool supportNonInlineArray = false,
}) {
_logger.fine('${_padding}getCodeGenType ${cxtype.completeStringRepr()}');

Expand Down Expand Up @@ -121,12 +122,13 @@ Type getCodeGenType(
case clang_types.CXTypeKind.CXType_ConstantArray:
// Primarily used for constant array in struct members.
final numElements = clang.clang_getNumElements(cxtype);
final elementType =
clang.clang_getArrayElementType(cxtype).toCodeGenType();
final elementType = clang
.clang_getArrayElementType(cxtype)
.toCodeGenType(supportNonInlineArray: supportNonInlineArray);
// Handle numElements being 0 as an incomplete array.
return numElements == 0
? IncompleteArray(elementType)
: ConstantArray(numElements, elementType);
: ConstantArray(numElements, supportNonInlineArray, elementType);
case clang_types.CXTypeKind.CXType_IncompleteArray:
// Primarily used for incomplete array in function parameters.
return IncompleteArray(
Expand Down
4 changes: 2 additions & 2 deletions pkgs/ffigen/lib/src/header_parser/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ String? removeRawCommentMarkups(String? string) {

extension CXTypeExt on clang_types.CXType {
/// Get code_gen [Type] representation of [clang_types.CXType].
Type toCodeGenType() {
return getCodeGenType(this);
Type toCodeGenType({bool supportNonInlineArray = false}) {
return getCodeGenType(this, supportNonInlineArray: supportNonInlineArray);
}

/// Spelling for a [clang_types.CXTypeKind], useful for debug purposes.
Expand Down

0 comments on commit 01e7752

Please sign in to comment.