[ffigen] Add the ability to control reference counting behavior in castFromPointer (#388)
diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart index 4c77067..04eb6e5 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart
@@ -103,8 +103,9 @@ } /// Returns a [$name] that wraps the given raw object pointer. - static $name castFromPointer($natLib lib, ffi.Pointer<ObjCObject> other) { - return $name._(other, lib, retain: true, release: true); + static $name castFromPointer($natLib lib, ffi.Pointer<ObjCObject> other, + {bool retain = false, bool release = false}) { + return $name._(other, lib, retain: retain, release: release); } /// Returns whether [obj] is an instance of [$name].
diff --git a/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart b/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart index 2c3ab47..74c1270 100644 --- a/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart +++ b/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.dart
@@ -97,6 +97,38 @@ calloc.free(counter); }); + castFromPointerInnerReleaseAndRetain(int address) { + final fromCast = RefCounted.castFromPointer( + lib, Pointer<ObjCObject>.fromAddress(address), + release: true, retain: true); + expect(fromCast.refCount, 2); + } + + test('castFromPointer - release and retain', () { + final obj1 = RefCounted.new1(lib); + expect(obj1.refCount, 1); + + castFromPointerInnerReleaseAndRetain(obj1.meAsInt()); + doGC(); + expect(obj1.refCount, 1); + }); + + castFromPointerInnerNoReleaseAndRetain(int address) { + final fromCast = RefCounted.castFromPointer( + lib, Pointer<ObjCObject>.fromAddress(address), + release: false, retain: false); + expect(fromCast.refCount, 1); + } + + test('castFromPointer - no release and retain', () { + final obj1 = RefCounted.new1(lib); + expect(obj1.refCount, 1); + + castFromPointerInnerNoReleaseAndRetain(obj1.meAsInt()); + doGC(); + expect(obj1.refCount, 1); + }); + test('Manual release', () { final counter = calloc<Int32>(); final obj1 = ArcTestObject.newWithCounter_(lib, counter);
diff --git a/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.m b/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.m index 4fa6c10..78e5a6b 100644 --- a/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.m +++ b/pkgs/ffigen/test/native_objc_test/automated_ref_count_test.m
@@ -20,6 +20,14 @@ @end +@interface RefCounted : NSObject + +@property(readonly) uint64_t refCount; + +- (int64_t) meAsInt; + +@end + @implementation ArcTestObject + (instancetype)allocTheThing { @@ -63,3 +71,30 @@ } @end + +@implementation RefCounted + +- (instancetype)init { + if (self = [super init]) { + self->_refCount = 1; + } + return self; +} + +- (instancetype)retain { + ++self->_refCount; + return self; +} + +- (oneway void)release { + --self->_refCount; + if (self->_refCount == 0) { + [self dealloc]; + } +} + +- (int64_t) meAsInt { + return (int64_t) self; +} + +@end \ No newline at end of file