blob: 688c573cb31ca47a455ca3a3d57aef61edb7f133 [file] [log] [blame]
// 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 'package:meta/meta.dart';
import 'binding.dart';
import 'binding_string.dart';
import 'type.dart';
import 'writer.dart';
/// A binding for C function.
///
/// For a C function -
/// ```c
/// int sum(int a, int b);
/// ```
/// The Generated dart code is -
/// ```dart
/// int sum(int a, int b) {
/// return _sum(a, b);
/// }
///
/// final _dart_sum _sum = _dylib.lookupFunction<_c_sum, _dart_sum>('sum');
///
/// typedef _c_sum = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b);
///
/// typedef _dart_sum = int Function(int a, int b);
/// ```
class Func extends Binding {
final Type returnType;
final List<Parameter> parameters;
Func({
@required String name,
String dartDoc,
@required this.returnType,
List<Parameter> parameters,
}) : parameters = parameters ?? [],
super(name: name, dartDoc: dartDoc) {
for (var i = 0; i < this.parameters.length; i++) {
if (this.parameters[i].name == null ||
this.parameters[i].name.trim() == '') {
this.parameters[i].name = 'arg$i';
}
}
}
@override
BindingString toBindingString(Writer w) {
final s = StringBuffer();
final funcVarName = '_$name';
final typedefC = '_c_$name';
final typedefDart = '_dart_$name';
if (dartDoc != null) {
s.write('/// ');
s.writeAll(dartDoc.split('\n'), '\n/// ');
s.write('\n');
}
// Write enclosing function.
s.write('${returnType.getDartType(w)} $name(\n');
for (final p in parameters) {
s.write(' ${p.type.getDartType(w)} ${p.name},\n');
}
s.write(') {\n');
s.write(' return $funcVarName(\n');
for (final p in parameters) {
s.write(' ${p.name},\n');
}
s.write(' );\n');
s.write('}\n\n');
// Write function with dylib lookup.
s.write(
"final $typedefDart $funcVarName = ${w.dylibIdentifier}.lookupFunction<$typedefC,$typedefDart>('$name');\n\n");
// Write typdef for C.
s.write('typedef $typedefC = ${returnType.getCType(w)} Function(\n');
for (final p in parameters) {
s.write(' ${p.type.getCType(w)} ${p.name},\n');
}
s.write(');\n\n');
// Write typdef for dart.
s.write('typedef $typedefDart = ${returnType.getDartType(w)} Function(\n');
for (final p in parameters) {
s.write(' ${p.type.getDartType(w)} ${p.name},\n');
}
s.write(');\n\n');
return BindingString(type: BindingStringType.func, string: s.toString());
}
}
/// Represents a Function's parameter.
class Parameter {
String name;
final Type type;
Parameter({this.name, @required this.type});
}