Skip to content

Commit

Permalink
[ffigen] Handle the argument consumed annotation (#1476)
Browse files Browse the repository at this point in the history
  • Loading branch information
liamappelbe authored Aug 30, 2024
1 parent c2fdaa5 commit 0ed2be1
Show file tree
Hide file tree
Showing 23 changed files with 206 additions and 47 deletions.
15 changes: 10 additions & 5 deletions pkgs/ffigen/lib/src/code_generator/func.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ class Func extends LookUpBinding {
.join('');

final argString = functionType.dartTypeParameters.map((p) {
final type =
p.type.convertDartTypeToFfiDartType(w, p.name, objCRetain: false);
final type = p.type.convertDartTypeToFfiDartType(w, p.name,
objCRetain: p.objCConsumed);
return '$type,\n';
}).join('');
funcImplCall = functionType.returnType.convertFfiDartTypeToDartType(
Expand Down Expand Up @@ -228,9 +228,14 @@ class Parameter {
final String? originalName;
String name;
final Type type;

Parameter({String? originalName, this.name = '', required Type type})
: originalName = originalName ?? name,
final bool objCConsumed;

Parameter({
String? originalName,
this.name = '',
required Type type,
required this.objCConsumed,
}) : originalName = originalName ?? name,
// A [NativeFunc] is wrapped with a pointer because this is a shorthand
// used in C for Pointer to function.
type = type.typealiasType is NativeFunc ? PointerType(type) : type;
Expand Down
1 change: 1 addition & 0 deletions pkgs/ffigen/lib/src/code_generator/func_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class FunctionType extends Type {
type: parameters[i].type,
originalName: names[i],
name: finalName,
objCConsumed: false,
);
}
}
Expand Down
12 changes: 7 additions & 5 deletions pkgs/ffigen/lib/src/code_generator/objc_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ class ObjCBlock extends BindingType {

final params = <Parameter>[];
for (var i = 0; i < argTypes.length; ++i) {
params.add(Parameter(name: 'arg$i', type: argTypes[i]));
params.add(
Parameter(name: 'arg$i', type: argTypes[i], objCConsumed: false));
}

final voidPtr = PointerType(voidType).getCType(w);
Expand All @@ -95,9 +96,10 @@ class ObjCBlock extends BindingType {
final newPointerBlock = ObjCBuiltInFunctions.newPointerBlock.gen(w);
final newClosureBlock = ObjCBuiltInFunctions.newClosureBlock.gen(w);
final getBlockClosure = ObjCBuiltInFunctions.getBlockClosure.gen(w);
final trampFuncType = FunctionType(
returnType: returnType,
parameters: [Parameter(type: blockPtr, name: 'block'), ...params]);
final trampFuncType = FunctionType(returnType: returnType, parameters: [
Parameter(type: blockPtr, name: 'block', objCConsumed: false),
...params
]);
final trampFuncCType = trampFuncType.getCType(w, writeArgumentNames: false);
final trampFuncFfiDartType =
trampFuncType.getFfiDartType(w, writeArgumentNames: false);
Expand Down Expand Up @@ -292,7 +294,7 @@ $blockTypedef $fnName($blockTypedef block) NS_RETURNS_RETAINED {
_wrapListenerBlock = Func(
name: 'wrapListenerBlock_$name',
returnType: this,
parameters: [Parameter(name: 'block', type: this)],
parameters: [Parameter(name: 'block', type: this, objCConsumed: false)],
objCReturnsRetained: true,
isLeaf: true,
isInternal: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,11 @@ class ObjCMsgSendFunc {
static List<Parameter> _params(List<ObjCMethodParam> params,
{Type? structRetPtr}) {
return [
if (structRetPtr != null) Parameter(type: structRetPtr),
Parameter(type: PointerType(objCObjectType)),
Parameter(type: PointerType(objCSelType)),
for (final p in params) Parameter(type: p.type),
if (structRetPtr != null)
Parameter(type: structRetPtr, objCConsumed: false),
Parameter(type: PointerType(objCObjectType), objCConsumed: false),
Parameter(type: PointerType(objCSelType), objCConsumed: false),
for (final p in params) Parameter(type: p.type, objCConsumed: false),
];
}

Expand Down
31 changes: 17 additions & 14 deletions pkgs/ffigen/lib/src/code_generator/objc_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,11 @@ class ObjCInterface extends BindingType with ObjCMethods {
type: BindingStringType.objcInterface, string: '');
}

String paramsToString(List<ObjCMethodParam> params,
{required bool isStatic}) {
final stringParams = <String>[];

stringParams.addAll(
params.map((p) => '${_getConvertedType(p.type, w, name)} ${p.name}'));
String paramsToString(List<ObjCMethodParam> params) {
final stringParams = <String>[
for (final p in params)
'${_getConvertedType(p.type, w, name)} ${p.name}',
];
return '(${stringParams.join(", ")})';
}

Expand Down Expand Up @@ -120,7 +119,10 @@ class ObjCInterface extends BindingType with ObjCMethods {
var returnType = m.returnType;
var params = m.params;
if (isStret) {
params = [ObjCMethodParam(PointerType(returnType), 'stret'), ...params];
params = [
ObjCMethodParam(PointerType(returnType), 'stret', consumed: false),
...params
];
returnType = voidType;
}

Expand Down Expand Up @@ -148,22 +150,22 @@ class ObjCInterface extends BindingType with ObjCMethods {
s.write(methodName[0].toUpperCase() + methodName.substring(1));
break;
}
s.write(paramsToString(params, isStatic: true));
s.write(paramsToString(params));
} else {
switch (m.kind) {
case ObjCMethodKind.method:
// returnType methodName(...)
s.write(_getConvertedType(returnType, w, name));
s.write(' $methodName');
s.write(paramsToString(params, isStatic: false));
s.write(paramsToString(params));
break;
case ObjCMethodKind.propertyGetter:
s.write(_getConvertedType(returnType, w, name));
if (isStret) {
// void getMethodName(Pointer<returnType> stret)
s.write(' get');
s.write(methodName[0].toUpperCase() + methodName.substring(1));
s.write(paramsToString(params, isStatic: false));
s.write(paramsToString(params));
} else {
// returnType get methodName
s.write(' get $methodName');
Expand All @@ -172,7 +174,7 @@ class ObjCInterface extends BindingType with ObjCMethods {
case ObjCMethodKind.propertySetter:
// set methodName(...)
s.write(' set $methodName');
s.write(paramsToString(params, isStatic: false));
s.write(paramsToString(params));
break;
}
}
Expand All @@ -194,7 +196,7 @@ class ObjCInterface extends BindingType with ObjCMethods {
objCRetain: m.consumesSelf),
m.selObject!.name,
m.params.map((p) => p.type
.convertDartTypeToFfiDartType(w, p.name, objCRetain: false)),
.convertDartTypeToFfiDartType(w, p.name, objCRetain: p.consumed)),
structRetPtr: 'stret'));
s.write(';\n');
if (convertReturn) {
Expand Down Expand Up @@ -225,8 +227,9 @@ class ObjCInterface extends BindingType with ObjCMethods {
(Writer w) => '${ObjCBuiltInFunctions.getClass.gen(w)}("$lookupName")')
..addDependencies(dependencies);
_isKindOfClass = builtInFunctions.getSelObject('isKindOfClass:');
_isKindOfClassMsgSend = builtInFunctions.getMsgSendFunc(
BooleanType(), [ObjCMethodParam(PointerType(objCObjectType), 'clazz')]);
_isKindOfClassMsgSend = builtInFunctions.getMsgSendFunc(BooleanType(), [
ObjCMethodParam(PointerType(objCObjectType), 'clazz', consumed: false)
]);

addMethodDependencies(dependencies, needMsgSend: true);

Expand Down
7 changes: 6 additions & 1 deletion pkgs/ffigen/lib/src/code_generator/objc_methods.dart
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,12 @@ class ObjCMethod {
class ObjCMethodParam {
Type type;
final String name;
ObjCMethodParam(this.type, this.name);
final bool consumed;
ObjCMethodParam(
this.type,
this.name, {
required this.consumed,
});

@override
String toString() => '$type $name';
Expand Down
3 changes: 2 additions & 1 deletion pkgs/ffigen/lib/src/code_generator/objc_protocol.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class ObjCProtocol extends NoLookUpBinding with ObjCMethods {
// The function type omits the first arg of the block, which is unused.
final func = FunctionType(returnType: block.returnType, parameters: [
for (int i = 1; i < block.argTypes.length; ++i)
Parameter(name: 'arg$i', type: block.argTypes[i]),
Parameter(
name: 'arg$i', type: block.argTypes[i], objCConsumed: false),
]);
final funcType = func.getDartType(w, writeArgumentNames: false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ List<Func> parseFunctionDeclaration(clang_types.CXCursor cursor) {
}

final paramName = paramCursor.spelling();
final objCConsumed = paramCursor
.hasChildWithKind(clang_types.CXCursorKind.CXCursor_NSConsumed);

/// If [paramName] is null or empty, its set to `arg$i` by code_generator.
parameters.add(
Parameter(
originalName: paramName,
name: config.functionDecl.renameMember(decl, paramName),
type: paramType,
objCConsumed: objCConsumed,
),
);
}
Expand Down Expand Up @@ -121,8 +124,9 @@ List<Func> parseFunctionDeclaration(clang_types.CXCursor cursor) {
originalName: funcName,
returnType: returnType,
parameters: parameters,
varArgParameters:
vaFunc.types.map((ta) => Parameter(type: ta, name: 'va')).toList(),
varArgParameters: vaFunc.types
.map((ta) => Parameter(type: ta, name: 'va', objCConsumed: false))
.toList(),
exposeSymbolAddress:
config.functionDecl.shouldIncludeSymbolAddress(decl),
exposeFunctionTypedefs: config.shouldExposeFunctionTypedef(decl),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void _parseProperty(clang_types.CXCursor cursor, ObjCInterface itf) {
returnType: NativeType(SupportedNativeType.voidType),
family: null,
);
setter.params.add(ObjCMethodParam(fieldType, 'value'));
setter.params.add(ObjCMethodParam(fieldType, 'value', consumed: false));
itf.addMethod(setter);
}
}
Expand Down Expand Up @@ -249,7 +249,9 @@ bool _parseMethodParam(
}
_logger.fine(
' >> Parameter: $type $name ${cursor.completeStringRepr()}');
method.params.add(ObjCMethodParam(type, name));
final consumed =
cursor.hasChildWithKind(clang_types.CXCursorKind.CXCursor_NSConsumed);
method.params.add(ObjCMethodParam(type, name, consumed: consumed));
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ Type _extractFromFunctionProto(clang_types.CXType cxtype,
}

parameters.add(
Parameter(name: '', type: pt),
Parameter(name: '', type: pt, objCConsumed: false),
);
}

Expand Down
42 changes: 35 additions & 7 deletions pkgs/ffigen/test/code_generator_tests/code_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@ void main() {
type: NativeType(
SupportedNativeType.int32,
),
objCConsumed: false,
),
Parameter(
name: 'b',
type: NativeType(
SupportedNativeType.uint8,
),
objCConsumed: false,
),
],
returnType: NativeType(
Expand All @@ -76,6 +78,7 @@ void main() {
SupportedNativeType.int32,
),
),
objCConsumed: false,
),
Parameter(
name: 'b',
Expand All @@ -86,6 +89,7 @@ void main() {
),
),
),
objCConsumed: false,
),
],
returnType: PointerType(
Expand All @@ -105,6 +109,7 @@ void main() {
type: NativeType(
SupportedNativeType.int32,
),
objCConsumed: false,
),
],
returnType: NativeType(
Expand Down Expand Up @@ -247,6 +252,7 @@ void main() {
structSome,
),
),
objCConsumed: false,
),
],
returnType: PointerType(
Expand Down Expand Up @@ -436,12 +442,24 @@ void main() {
Func(
name: 'acceptsEnum',
returnType: enum1,
parameters: [Parameter(name: 'value', type: enum1)],
parameters: [
Parameter(
name: 'value',
type: enum1,
objCConsumed: false,
)
],
),
Func(
name: 'acceptsInt',
returnType: enum2,
parameters: [Parameter(name: 'value', type: enum2)],
parameters: [
Parameter(
name: 'value',
type: enum2,
objCConsumed: false,
)
],
),
],
);
Expand Down Expand Up @@ -589,8 +607,16 @@ void main() {
name: 'test1',
returnType: BooleanType(),
parameters: [
Parameter(name: 'a', type: BooleanType()),
Parameter(name: 'b', type: PointerType(BooleanType())),
Parameter(
name: 'a',
type: BooleanType(),
objCConsumed: false,
),
Parameter(
name: 'b',
type: PointerType(BooleanType()),
objCConsumed: false,
),
],
),
Struct(
Expand Down Expand Up @@ -714,9 +740,11 @@ void main() {
parameters: []))),
parameters: [
Parameter(
name: 't',
type: Typealias(
name: 'Struct3Typealias', type: Struct(name: 'Struct3')))
name: 't',
type: Typealias(
name: 'Struct3Typealias', type: Struct(name: 'Struct3')),
objCConsumed: false,
)
]),
],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@ void main() {
Parameter(
type: intType,
name: 'if',
objCConsumed: false,
),
Parameter(
type: intType,
name: 'abstract',
objCConsumed: false,
),
Parameter(
type: intType,
name: 'in',
objCConsumed: false,
),
],
returnType: NativeType(SupportedNativeType.voidType)),
Expand Down
Loading

0 comments on commit 0ed2be1

Please sign in to comment.