From dddcc97642afbf4cf8ddc722311160561baa7801 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 15:26:15 +0200 Subject: [PATCH 01/10] updated deps --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index f78c325c..0a7175d0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,11 +3,11 @@ version: 0.3.0 description: >- ObjectBox binding for Dart. environment: - sdk: '>=2.5.0 <3.0.0' + sdk: '>=2.6.0-dev' dependencies: # take care updating flatbuffers - keep aligned with other bindings flat_buffers: 1.11.0 - ffi: 0.1.2 + ffi: ">=0.1.3-dev" dev_dependencies: build_runner: ^1.0.0 objectbox_model_generator: From f421734595259f5c295212fd52a648d7e70de971 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 16:33:43 +0200 Subject: [PATCH 02/10] Struct no longer takes a generic arg --- lib/src/bindings/structs.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/bindings/structs.dart b/lib/src/bindings/structs.dart index ff473ebf..e69b6003 100644 --- a/lib/src/bindings/structs.dart +++ b/lib/src/bindings/structs.dart @@ -3,7 +3,7 @@ import "dart:typed_data" show Uint8List, Uint64List; // Note: IntPtr seems to be the the correct representation for size_t: "Represents a native pointer-sized integer in C." -class OBX_id_array extends Struct { +class OBX_id_array extends Struct { /* typedef struct OBX_id_array { obx_id* ids; From 87542dbbc9770c2d517d808f50abe2cf9d649ad0 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 16:38:36 +0200 Subject: [PATCH 03/10] Replaced Pointer allocate / free with package:ffi's allocate and free We could have used extension methods to fix it without changing too many lines of code --- lib/src/bindings/structs.dart | 22 ++++++++++-------- lib/src/box.dart | 44 ++++++++++++++++++----------------- lib/src/common.dart | 9 +++---- lib/src/query/query.dart | 31 ++++++++++++------------ 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/lib/src/bindings/structs.dart b/lib/src/bindings/structs.dart index e69b6003..c2741512 100644 --- a/lib/src/bindings/structs.dart +++ b/lib/src/bindings/structs.dart @@ -1,6 +1,8 @@ import 'dart:ffi'; import "dart:typed_data" show Uint8List, Uint64List; +import "package:ffi/ffi.dart" show allocate, free; + // Note: IntPtr seems to be the the correct representation for size_t: "Represents a native pointer-sized integer in C." class OBX_id_array extends Struct { @@ -17,7 +19,7 @@ class OBX_id_array extends Struct { int length; /// Get a copy of the list - List items() => Uint64List.view(_itemsPtr.asExternalTypedData(count: length).buffer).toList(); + List items() => Uint64List.view(_itemsPtr.asTypedList(count: length).buffer).toList(); /// Execute the given function, managing the resources consistently static R executeWith(List items, R Function(Pointer) fn) { @@ -27,7 +29,7 @@ class OBX_id_array extends Struct { // fill it with data OBX_id_array array = ptr.load(); array.length = items.length; - array._itemsPtr = Pointer.allocate(count: array.length); + array._itemsPtr = allocate(count: array.length); for (int i = 0; i < items.length; ++i) { array._itemsPtr.elementAt(i).store(items[i]); } @@ -36,8 +38,8 @@ class OBX_id_array extends Struct { try { return fn(ptr); } finally { - array._itemsPtr.free(); - ptr.free(); + free(array._itemsPtr); + free(ptr); } } } @@ -49,7 +51,7 @@ class ByteBuffer { ByteBuffer(this._ptr, this._size); ByteBuffer.allocate(Uint8List dartData, [bool align = true]) { - _ptr = Pointer.allocate(count: align ? ((dartData.length + 3.0) ~/ 4.0) * 4 : dartData.length); + _ptr = allocate(count: align ? ((dartData.length + 3.0) ~/ 4.0) * 4 : dartData.length); for (int i = 0; i < dartData.length; ++i) { _ptr.elementAt(i).store(dartData[i]); } @@ -78,7 +80,7 @@ class ByteBuffer { return buffer; } - free() => _ptr.free(); + free() => free(_ptr); } class _SerializedByteBufferArray { @@ -90,8 +92,8 @@ class _SerializedByteBufferArray { get ptr => _outerPtr; free() { - _innerPtr.free(); - _outerPtr.free(); + free(_innerPtr); + free(_outerPtr); } } @@ -110,13 +112,13 @@ class ByteBufferArray { } _SerializedByteBufferArray toOBXBytesArray() { - Pointer bufferPtrs = Pointer.allocate(count: _buffers.length * 2); + Pointer bufferPtrs = allocate(count: _buffers.length * 2); for (int i = 0; i < _buffers.length; ++i) { bufferPtrs.elementAt(2 * i).store(_buffers[i].ptr.address as int); bufferPtrs.elementAt(2 * i + 1).store(_buffers[i].size as int); } - Pointer outerPtr = Pointer.allocate(count: 2); + Pointer outerPtr = allocate(count: 2); outerPtr.store(bufferPtrs.address); outerPtr.elementAt(1).store(_buffers.length); return _SerializedByteBufferArray(outerPtr, bufferPtrs); diff --git a/lib/src/box.dart b/lib/src/box.dart index 3c7b6c14..e41bcd50 100644 --- a/lib/src/box.dart +++ b/lib/src/box.dart @@ -1,5 +1,7 @@ import "dart:ffi"; +import "package:ffi/ffi.dart" show allocate, free; + import 'common.dart'; import "store.dart"; import "bindings/bindings.dart"; @@ -58,7 +60,7 @@ class Box { checkObx(bindings.obx_box_put( _cBox, propVals[_modelEntity.idPropName], buffer.voidPtr, buffer.size, _getOBXPutMode(mode))); } finally { - buffer.free(); + free(buffer); } return propVals[_modelEntity.idPropName]; } @@ -79,12 +81,12 @@ class Box { // generate new IDs for these instances and set them if (missingIdsCount != 0) { int nextId = 0; - Pointer nextIdPtr = Pointer.allocate(count: 1); + Pointer nextIdPtr = allocate(count: 1); try { checkObx(bindings.obx_box_ids_for_put(_cBox, missingIdsCount, nextIdPtr)); nextId = nextIdPtr.load(); } finally { - nextIdPtr.free(); + free(nextIdPtr); } for (var instPropVals in allPropVals) { if (instPropVals[_modelEntity.idPropName] == null || instPropVals[_modelEntity.idPropName] == 0) { @@ -95,7 +97,7 @@ class Box { // because obx_box_put_many also needs a list of all IDs of the elements to be put into the box, // generate this list now (only needed if not all IDs have been generated) - Pointer allIdsMemory = Pointer.allocate(count: objects.length); + Pointer allIdsMemory = allocate(count: objects.length); try { for (int i = 0; i < allPropVals.length; ++i) { allIdsMemory.elementAt(i).store(allPropVals[i][_modelEntity.idPropName] as int); @@ -109,14 +111,14 @@ class Box { putObjects.free(); } } finally { - allIdsMemory.free(); + free(allIdsMemory); } return allPropVals.map((p) => p[_modelEntity.idPropName] as int).toList(); } get(int id) { - Pointer> dataPtr = Pointer>.allocate(); - Pointer sizePtr = Pointer.allocate(); + Pointer> dataPtr = allocate>(); + Pointer sizePtr = allocate(); // get element with specified id from database return _store.runInTransaction(TxMode.Read, () { @@ -130,8 +132,8 @@ class Box { // transform bytes from memory to Dart byte list buffer = ByteBuffer(data, size); } finally { - dataPtr.free(); - sizePtr.free(); + free(dataPtr); + free(sizePtr); } return _fbManager.unmarshal(buffer); @@ -167,44 +169,44 @@ class Box { QueryBuilder query(Condition qc) => QueryBuilder(_store, _fbManager, _modelEntity.id.id, qc); int count({int limit = 0}) { - Pointer count = Pointer.allocate(); + Pointer count = allocate(); try { checkObx(bindings.obx_box_count(_cBox, limit, count)); return count.load(); } finally { - count.free(); + free(count); } } bool isEmpty() { - Pointer isEmpty = Pointer.allocate(); + Pointer isEmpty = allocate(); try { checkObx(bindings.obx_box_is_empty(_cBox, isEmpty)); return isEmpty.load() > 0 ? true : false; } finally { - isEmpty.free(); + free(isEmpty); } } bool contains(int id) { - Pointer contains = Pointer.allocate(); + Pointer contains = allocate(); try { checkObx(bindings.obx_box_contains(_cBox, id, contains)); return contains.load() > 0 ? true : false; } finally { - contains.free(); + free(contains); } } bool containsMany(List ids) { - Pointer contains = Pointer.allocate(); + Pointer contains = allocate(); try { return OBX_id_array.executeWith(ids, (ptr) { checkObx(bindings.obx_box_contains_many(_cBox, ptr, contains)); return contains.load() > 0 ? true : false; }); } finally { - contains.free(); + free(contains); } } @@ -221,24 +223,24 @@ class Box { } int removeMany(List ids) { - Pointer removedIds = Pointer.allocate(); + Pointer removedIds = allocate(); try { return OBX_id_array.executeWith(ids, (ptr) { checkObx(bindings.obx_box_remove_many(_cBox, ptr, removedIds)); return removedIds.load(); }); } finally { - removedIds.free(); + free(removedIds); } } int removeAll() { - Pointer removedItems = Pointer.allocate(); + Pointer removedItems = allocate(); try { checkObx(bindings.obx_box_remove_all(_cBox, removedItems)); return removedItems.load(); } finally { - removedItems.free(); + free(removedItems); } } diff --git a/lib/src/common.dart b/lib/src/common.dart index c0f5149d..b1a5acf2 100644 --- a/lib/src/common.dart +++ b/lib/src/common.dart @@ -1,4 +1,5 @@ import "dart:ffi"; +import "package:ffi/ffi.dart" show allocate, free; import "bindings/bindings.dart"; @@ -14,15 +15,15 @@ class Version { /// Returns the underlying ObjectBox-C library version Version versionLib() { - var majorPtr = Pointer.allocate(), minorPtr = Pointer.allocate(), patchPtr = Pointer.allocate(); + var majorPtr = allocate(), minorPtr = allocate(), patchPtr = allocate(); try { bindings.obx_version(majorPtr, minorPtr, patchPtr); return Version(majorPtr.load(), minorPtr.load(), patchPtr.load()); } finally { - majorPtr.free(); - minorPtr.free(); - patchPtr.free(); + free(majorPtr); + free(minorPtr); + free(patchPtr); } } diff --git a/lib/src/query/query.dart b/lib/src/query/query.dart index ae6a6ef3..8b2a80bd 100644 --- a/lib/src/query/query.dart +++ b/lib/src/query/query.dart @@ -2,6 +2,8 @@ library query; import "dart:ffi"; +import "package:ffi/ffi.dart" show allocate, free; + import "../store.dart"; import "../common.dart"; import "../bindings/bindings.dart"; @@ -10,7 +12,6 @@ import "../bindings/flatbuffers.dart"; import "../bindings/helpers.dart"; import "../bindings/structs.dart"; import "../bindings/signatures.dart"; -import "package:ffi/ffi.dart"; part "builder.dart"; @@ -286,7 +287,7 @@ class StringCondition extends PropertyCondition { int _inside(QueryBuilder builder) { final func = bindings.obx_qb_string_in; final listLength = _list.length; - final arrayOfUint8Ptrs = Pointer>.allocate(count: listLength); + final arrayOfUint8Ptrs = allocate>(count: listLength); try { for (int i = 0; i < _list.length; i++) { var uint8Str = Utf8.toUtf8(_list[i]).cast(); @@ -296,9 +297,9 @@ class StringCondition extends PropertyCondition { } finally { for (int i = 0; i < _list.length; i++) { var uint8Str = arrayOfUint8Ptrs.elementAt(i).load(); - uint8Str.free(); // I assume the casted Uint8 retains the same Utf8 address + free(uint8Str); // I assume the casted Uint8 retains the same Utf8 address } - arrayOfUint8Ptrs.free(); // It probably doesn't release recursively + free(arrayOfUint8Ptrs); // It probably doesn't release recursively } } @@ -350,19 +351,19 @@ class IntegerCondition extends PropertyCondition { return func(builder._cBuilder, _property._propertyId, _value); } - // ideally it should be implemented like this, but this doesn't work, TODO report to google + // ideally it should be implemented like this, but this doesn't work, TODO try this out on dart-2.6 /* int _opList

(QueryBuilder builder, obx_qb_cond_operator_in_dart_t

func) { int length = _list.length; - final listPtr = Pointer

.allocate(count: length); + final listPtr = allocate

(count: length); try { for (int i=0; i { // TODO replace nasty duplication with implementation above, when fix is in int _opList32(QueryBuilder builder, obx_qb_cond_operator_in_dart_t func) { int length = _list.length; - final listPtr = Pointer.allocate(count: length); + final listPtr = allocate(count: length); try { for (int i = 0; i < length; i++) { listPtr.elementAt(i).store(_list[i]); } return func(builder._cBuilder, _property._propertyId, listPtr, length); } finally { - listPtr.free(); + free(listPtr); } } // TODO replace duplication with implementation above, when fix is in int _opList64(QueryBuilder builder, obx_qb_cond_operator_in_dart_t func) { int length = _list.length; - final listPtr = Pointer.allocate(count: length); + final listPtr = allocate(count: length); try { for (int i = 0; i < length; i++) { listPtr.elementAt(i).store(_list[i]); } return func(builder._cBuilder, _property._propertyId, listPtr, length); } finally { - listPtr.free(); + free(listPtr); } } @@ -482,7 +483,7 @@ class ConditionGroup extends Condition { return _conditions[0].apply(builder, isRoot); } - final intArrayPtr = Pointer.allocate(count: size); + final intArrayPtr = allocate(count: size); try { for (int i = 0; i < size; ++i) { final cid = _conditions[i].apply(builder, false); @@ -501,7 +502,7 @@ class ConditionGroup extends Condition { return _func(builder._cBuilder, intArrayPtr, size); } finally { - intArrayPtr.free(); + free(intArrayPtr); } } } @@ -525,12 +526,12 @@ class Query { } int count() { - final ptr = Pointer.allocate(count: 1); + final ptr = allocate(count: 1); try { checkObx(bindings.obx_query_count(_cQuery, ptr)); return ptr.load(); } finally { - ptr.free(); + free(ptr); } } From 3cabbfe10f566d0a862b872d2e5280ce71bfd27d Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 17:36:23 +0200 Subject: [PATCH 04/10] replace load/store with value replace allocate/free with package:ffi's --- lib/src/bindings/structs.dart | 29 ++++++++++++++++------------- lib/src/box.dart | 22 +++++++++++----------- lib/src/common.dart | 2 +- lib/src/model.dart | 4 ++-- lib/src/query/query.dart | 18 +++++++++--------- lib/src/store.dart | 6 +++--- 6 files changed, 42 insertions(+), 39 deletions(-) diff --git a/lib/src/bindings/structs.dart b/lib/src/bindings/structs.dart index c2741512..6b2cf52d 100644 --- a/lib/src/bindings/structs.dart +++ b/lib/src/bindings/structs.dart @@ -24,14 +24,14 @@ class OBX_id_array extends Struct { /// Execute the given function, managing the resources consistently static R executeWith(List items, R Function(Pointer) fn) { // allocate a temporary structure - final ptr = Pointer.allocate(); + final ptr = allocate(); // fill it with data - OBX_id_array array = ptr.load(); + OBX_id_array array = ptr.value; array.length = items.length; array._itemsPtr = allocate(count: array.length); for (int i = 0; i < items.length; ++i) { - array._itemsPtr.elementAt(i).store(items[i]); + array._itemsPtr.elementAt(i).value = items[i]; } // call the function with the structure and free afterwards @@ -44,6 +44,7 @@ class OBX_id_array extends Struct { } } +// TODO change to a struct class ByteBuffer { Pointer _ptr; int _size; @@ -53,15 +54,15 @@ class ByteBuffer { ByteBuffer.allocate(Uint8List dartData, [bool align = true]) { _ptr = allocate(count: align ? ((dartData.length + 3.0) ~/ 4.0) * 4 : dartData.length); for (int i = 0; i < dartData.length; ++i) { - _ptr.elementAt(i).store(dartData[i]); + _ptr.elementAt(i).value = dartData[i]; } _size = dartData.length; } ByteBuffer.fromOBXBytes(Pointer obxPtr) { // extract fields from "struct OBX_bytes" - _ptr = Pointer.fromAddress(obxPtr.load()); - _size = obxPtr.elementAt(1).load(); + _ptr = Pointer.fromAddress(obxPtr.value); + _size = obxPtr.elementAt(1).value; } get ptr => _ptr; @@ -75,7 +76,7 @@ class ByteBuffer { Uint8List get data { var buffer = Uint8List(size); for (int i = 0; i < size; ++i) { - buffer[i] = _ptr.elementAt(i).load(); + buffer[i] = _ptr.elementAt(i).value; } return buffer; } @@ -83,6 +84,7 @@ class ByteBuffer { free() => free(_ptr); } +// TODO change to a struct class _SerializedByteBufferArray { Pointer _outerPtr, _innerPtr; // outerPtr points to the instance itself, innerPtr points to the respective OBX_bytes_array.bytes @@ -97,6 +99,7 @@ class _SerializedByteBufferArray { } } +// TODO change to a struct class ByteBufferArray { List _buffers; @@ -104,8 +107,8 @@ class ByteBufferArray { ByteBufferArray.fromOBXBytesArray(Pointer bytesArray) { _buffers = []; - Pointer bufferPtrs = Pointer.fromAddress(bytesArray.load()); // bytesArray.bytes - int numBuffers = bytesArray.elementAt(1).load(); // bytesArray.count + Pointer bufferPtrs = Pointer.fromAddress(bytesArray.value); // bytesArray.bytes + int numBuffers = bytesArray.elementAt(1).value; // bytesArray.count for (int i = 0; i < numBuffers; ++i) { _buffers.add(ByteBuffer.fromOBXBytes(bufferPtrs.elementAt(2 * i))); } // 2 * i, because each instance of "struct OBX_bytes" has .data and .size @@ -114,13 +117,13 @@ class ByteBufferArray { _SerializedByteBufferArray toOBXBytesArray() { Pointer bufferPtrs = allocate(count: _buffers.length * 2); for (int i = 0; i < _buffers.length; ++i) { - bufferPtrs.elementAt(2 * i).store(_buffers[i].ptr.address as int); - bufferPtrs.elementAt(2 * i + 1).store(_buffers[i].size as int); + bufferPtrs.elementAt(2 * i).value = _buffers[i].ptr.address as int; + bufferPtrs.elementAt(2 * i + 1).value = buffers[i].size as int; } Pointer outerPtr = allocate(count: 2); - outerPtr.store(bufferPtrs.address); - outerPtr.elementAt(1).store(_buffers.length); + outerPtr.value = bufferPtrs.address; + outerPtr.elementAt(1).value = _buffers.length; return _SerializedByteBufferArray(outerPtr, bufferPtrs); } diff --git a/lib/src/box.dart b/lib/src/box.dart index e41bcd50..2e90b0ab 100644 --- a/lib/src/box.dart +++ b/lib/src/box.dart @@ -60,7 +60,7 @@ class Box { checkObx(bindings.obx_box_put( _cBox, propVals[_modelEntity.idPropName], buffer.voidPtr, buffer.size, _getOBXPutMode(mode))); } finally { - free(buffer); + buffer.free(); // TODO change ByteBuffer to a struct } return propVals[_modelEntity.idPropName]; } @@ -84,7 +84,7 @@ class Box { Pointer nextIdPtr = allocate(count: 1); try { checkObx(bindings.obx_box_ids_for_put(_cBox, missingIdsCount, nextIdPtr)); - nextId = nextIdPtr.load(); + nextId = nextIdPtr.value; } finally { free(nextIdPtr); } @@ -100,7 +100,7 @@ class Box { Pointer allIdsMemory = allocate(count: objects.length); try { for (int i = 0; i < allPropVals.length; ++i) { - allIdsMemory.elementAt(i).store(allPropVals[i][_modelEntity.idPropName] as int); + allIdsMemory.elementAt(i).value = (allPropVals[i][_modelEntity.idPropName] as int); } // marshal all objects to be put into the box @@ -126,8 +126,8 @@ class Box { try { checkObx(bindings.obx_box_get(_cBox, id, dataPtr, sizePtr)); - Pointer data = Pointer.fromAddress(dataPtr.load>().address); - var size = sizePtr.load(); + Pointer data = Pointer.fromAddress(dataPtr.value.address); + var size = sizePtr.value; // transform bytes from memory to Dart byte list buffer = ByteBuffer(data, size); @@ -172,7 +172,7 @@ class Box { Pointer count = allocate(); try { checkObx(bindings.obx_box_count(_cBox, limit, count)); - return count.load(); + return count.value; } finally { free(count); } @@ -182,7 +182,7 @@ class Box { Pointer isEmpty = allocate(); try { checkObx(bindings.obx_box_is_empty(_cBox, isEmpty)); - return isEmpty.load() > 0 ? true : false; + return isEmpty.value > 0 ? true : false; } finally { free(isEmpty); } @@ -192,7 +192,7 @@ class Box { Pointer contains = allocate(); try { checkObx(bindings.obx_box_contains(_cBox, id, contains)); - return contains.load() > 0 ? true : false; + return contains.value > 0 ? true : false; } finally { free(contains); } @@ -203,7 +203,7 @@ class Box { try { return OBX_id_array.executeWith(ids, (ptr) { checkObx(bindings.obx_box_contains_many(_cBox, ptr, contains)); - return contains.load() > 0 ? true : false; + return contains.value > 0 ? true : false; }); } finally { free(contains); @@ -227,7 +227,7 @@ class Box { try { return OBX_id_array.executeWith(ids, (ptr) { checkObx(bindings.obx_box_remove_many(_cBox, ptr, removedIds)); - return removedIds.load(); + return removedIds.value; }); } finally { free(removedIds); @@ -238,7 +238,7 @@ class Box { Pointer removedItems = allocate(); try { checkObx(bindings.obx_box_remove_all(_cBox, removedItems)); - return removedItems.load(); + return removedItems.value; } finally { free(removedItems); } diff --git a/lib/src/common.dart b/lib/src/common.dart index b1a5acf2..d874df7d 100644 --- a/lib/src/common.dart +++ b/lib/src/common.dart @@ -19,7 +19,7 @@ Version versionLib() { try { bindings.obx_version(majorPtr, minorPtr, patchPtr); - return Version(majorPtr.load(), minorPtr.load(), patchPtr.load()); + return Version(majorPtr.value, minorPtr.value, patchPtr.value); } finally { free(majorPtr); free(minorPtr); diff --git a/lib/src/model.dart b/lib/src/model.dart index 334d6942..5d979181 100644 --- a/lib/src/model.dart +++ b/lib/src/model.dart @@ -22,7 +22,7 @@ class Model { var entityNamePointer = entityUtf8.cast(); checkObx(bindings.obx_model_entity(_cModel, entityNamePointer, currentEntity.id.id, currentEntity.id.uid)); } finally { - entityUtf8.free(); + free(entityUtf8); } // add all properties @@ -33,7 +33,7 @@ class Model { checkObx(bindings.obx_model_property(_cModel, propertyNamePointer, p.type, p.id.id, p.id.uid)); checkObx(bindings.obx_model_property_flags(_cModel, p.flags)); } finally { - propertyUtf8.free(); + free(propertyUtf8); } }); diff --git a/lib/src/query/query.dart b/lib/src/query/query.dart index 8b2a80bd..549dc848 100644 --- a/lib/src/query/query.dart +++ b/lib/src/query/query.dart @@ -2,7 +2,7 @@ library query; import "dart:ffi"; -import "package:ffi/ffi.dart" show allocate, free; +import "package:ffi/ffi.dart" show allocate, free, Utf8; import "../store.dart"; import "../common.dart"; @@ -291,12 +291,12 @@ class StringCondition extends PropertyCondition { try { for (int i = 0; i < _list.length; i++) { var uint8Str = Utf8.toUtf8(_list[i]).cast(); - arrayOfUint8Ptrs.elementAt(i).store(uint8Str); + arrayOfUint8Ptrs.elementAt(i).value = uint8Str; } return func(builder._cBuilder, _property._propertyId, arrayOfUint8Ptrs, listLength, _caseSensitive ? 1 : 0); } finally { for (int i = 0; i < _list.length; i++) { - var uint8Str = arrayOfUint8Ptrs.elementAt(i).load(); + var uint8Str = arrayOfUint8Ptrs.elementAt(i).value; free(uint8Str); // I assume the casted Uint8 retains the same Utf8 address } free(arrayOfUint8Ptrs); // It probably doesn't release recursively @@ -359,7 +359,7 @@ class IntegerCondition extends PropertyCondition { final listPtr = allocate

(count: length); try { for (int i=0; i { final listPtr = allocate(count: length); try { for (int i = 0; i < length; i++) { - listPtr.elementAt(i).store(_list[i]); + listPtr.elementAt(i).value = _list[i]; } return func(builder._cBuilder, _property._propertyId, listPtr, length); } finally { @@ -388,7 +388,7 @@ class IntegerCondition extends PropertyCondition { final listPtr = allocate(count: length); try { for (int i = 0; i < length; i++) { - listPtr.elementAt(i).store(_list[i]); + listPtr.elementAt(i).value = _list[i]; } return func(builder._cBuilder, _property._propertyId, listPtr, length); } finally { @@ -492,7 +492,7 @@ class ConditionGroup extends Condition { throw Exception("Failed to create condition " + _conditions[i].toString()); } - intArrayPtr.elementAt(i).store(cid); + intArrayPtr.elementAt(i).value = cid; } // root All (AND) is implicit so no need to actually combine the conditions @@ -529,7 +529,7 @@ class Query { final ptr = allocate(count: 1); try { checkObx(bindings.obx_query_count(_cQuery, ptr)); - return ptr.load(); + return ptr.value; } finally { free(ptr); } @@ -548,7 +548,7 @@ class Query { List findIds({int offset = 0, int limit = 0}) { final idArrayPtr = checkObxPtr(bindings.obx_query_find_ids(_cQuery, offset, limit), "find ids"); try { - OBX_id_array idArray = idArrayPtr.load(); + OBX_id_array idArray = idArrayPtr.value; return idArray.length == 0 ? List() : idArray.items(); } finally { bindings.obx_id_array_free(idArrayPtr); diff --git a/lib/src/store.dart b/lib/src/store.dart index ee579221..87fdc99e 100644 --- a/lib/src/store.dart +++ b/lib/src/store.dart @@ -27,11 +27,11 @@ class Store { try { checkObx(bindings.obx_opt_model(opt, model.ptr)); if (directory != null && directory.isNotEmpty) { - var cStr = Utf8.toUtf8(directory).cast(); + var cStr = Utf8.toUtf8(directory); try { - checkObx(bindings.obx_opt_directory(opt, cStr)); + checkObx(bindings.obx_opt_directory(opt, cStr.cast())); } finally { - cStr.free(); + free(cStr); } } if (maxDBSizeInKB != null && maxDBSizeInKB > 0) bindings.obx_opt_max_db_size_in_kb(opt, maxDBSizeInKB); From 37de6e17d6d5e7d68df24f0ae5817bafc886995a Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 18:14:31 +0200 Subject: [PATCH 05/10] added ref, so it seems that ref is being autogenerated --- lib/src/bindings/structs.dart | 2 +- lib/src/query/query.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/bindings/structs.dart b/lib/src/bindings/structs.dart index 6b2cf52d..5d942531 100644 --- a/lib/src/bindings/structs.dart +++ b/lib/src/bindings/structs.dart @@ -27,7 +27,7 @@ class OBX_id_array extends Struct { final ptr = allocate(); // fill it with data - OBX_id_array array = ptr.value; + OBX_id_array array = ptr.ref; array.length = items.length; array._itemsPtr = allocate(count: array.length); for (int i = 0; i < items.length; ++i) { diff --git a/lib/src/query/query.dart b/lib/src/query/query.dart index 549dc848..d4aa76e6 100644 --- a/lib/src/query/query.dart +++ b/lib/src/query/query.dart @@ -548,7 +548,7 @@ class Query { List findIds({int offset = 0, int limit = 0}) { final idArrayPtr = checkObxPtr(bindings.obx_query_find_ids(_cQuery, offset, limit), "find ids"); try { - OBX_id_array idArray = idArrayPtr.value; + OBX_id_array idArray = idArrayPtr.ref; return idArray.length == 0 ? List() : idArray.items(); } finally { bindings.obx_id_array_free(idArrayPtr); From 47255dcf9ed4b955e203d68356c10c12284b6514 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 18:36:20 +0200 Subject: [PATCH 06/10] prefixed ffi for a nameclash used asTypedList properly --- lib/src/bindings/structs.dart | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/src/bindings/structs.dart b/lib/src/bindings/structs.dart index 5d942531..0608f046 100644 --- a/lib/src/bindings/structs.dart +++ b/lib/src/bindings/structs.dart @@ -1,7 +1,7 @@ import 'dart:ffi'; import "dart:typed_data" show Uint8List, Uint64List; -import "package:ffi/ffi.dart" show allocate, free; +import "package:ffi/ffi.dart" as ffi show allocate, free; // Note: IntPtr seems to be the the correct representation for size_t: "Represents a native pointer-sized integer in C." @@ -19,17 +19,17 @@ class OBX_id_array extends Struct { int length; /// Get a copy of the list - List items() => Uint64List.view(_itemsPtr.asTypedList(count: length).buffer).toList(); + List items() => _itemsPtr.asTypedList(length); /// Execute the given function, managing the resources consistently static R executeWith(List items, R Function(Pointer) fn) { // allocate a temporary structure - final ptr = allocate(); + final ptr = ffi.allocate(); // fill it with data OBX_id_array array = ptr.ref; array.length = items.length; - array._itemsPtr = allocate(count: array.length); + array._itemsPtr = ffi.allocate(count: array.length); for (int i = 0; i < items.length; ++i) { array._itemsPtr.elementAt(i).value = items[i]; } @@ -38,8 +38,8 @@ class OBX_id_array extends Struct { try { return fn(ptr); } finally { - free(array._itemsPtr); - free(ptr); + ffi.free(array._itemsPtr); + ffi.free(ptr); } } } @@ -52,7 +52,7 @@ class ByteBuffer { ByteBuffer(this._ptr, this._size); ByteBuffer.allocate(Uint8List dartData, [bool align = true]) { - _ptr = allocate(count: align ? ((dartData.length + 3.0) ~/ 4.0) * 4 : dartData.length); + _ptr = ffi.allocate(count: align ? ((dartData.length + 3.0) ~/ 4.0) * 4 : dartData.length); for (int i = 0; i < dartData.length; ++i) { _ptr.elementAt(i).value = dartData[i]; } @@ -81,7 +81,8 @@ class ByteBuffer { return buffer; } - free() => free(_ptr); + // We're importing with the ffi alias because of this thing here + free() => ffi.free(_ptr); } // TODO change to a struct @@ -94,8 +95,8 @@ class _SerializedByteBufferArray { get ptr => _outerPtr; free() { - free(_innerPtr); - free(_outerPtr); + ffi.free(_innerPtr); + ffi.free(_outerPtr); } } @@ -115,13 +116,13 @@ class ByteBufferArray { } _SerializedByteBufferArray toOBXBytesArray() { - Pointer bufferPtrs = allocate(count: _buffers.length * 2); + Pointer bufferPtrs = ffi.allocate(count: _buffers.length * 2); for (int i = 0; i < _buffers.length; ++i) { bufferPtrs.elementAt(2 * i).value = _buffers[i].ptr.address as int; bufferPtrs.elementAt(2 * i + 1).value = buffers[i].size as int; } - Pointer outerPtr = allocate(count: 2); + Pointer outerPtr = ffi.allocate(count: 2); outerPtr.value = bufferPtrs.address; outerPtr.elementAt(1).value = _buffers.length; return _SerializedByteBufferArray(outerPtr, bufferPtrs); From 1499ec3791889175b3c1de7973b52e4b112ca694 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 18:51:27 +0200 Subject: [PATCH 07/10] fixed other struct issues --- lib/src/bindings/bindings.dart | 6 +++--- lib/src/bindings/signatures.dart | 1 - lib/src/query/query.dart | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/src/bindings/bindings.dart b/lib/src/bindings/bindings.dart index c75d8206..ebbe5185 100644 --- a/lib/src/bindings/bindings.dart +++ b/lib/src/bindings/bindings.dart @@ -18,8 +18,8 @@ class _ObjectBoxBindings { obx_int16_array_free, obx_int8_array_free, obx_double_array_free, - obx_float_array_free; - obx_free_t obx_id_array_free; + obx_float_array_free, + obx_id_array_free; // error info int Function() obx_last_error_code; @@ -145,7 +145,7 @@ class _ObjectBoxBindings { obx_version = _fn("obx_version").asFunction(); obx_version_string = _fn("obx_version_string").asFunction(); obx_bytes_array_free = _fn("obx_bytes_array_free").asFunction(); - obx_id_array_free = _fn>("obx_id_array_free").asFunction(); + obx_id_array_free = _fn("obx_id_array_free").asFunction(); obx_string_array_free = _fn("obx_string_array_free").asFunction(); obx_int64_array_free = _fn("obx_int64_array_free").asFunction(); obx_int32_array_free = _fn("obx_int32_array_free").asFunction(); diff --git a/lib/src/bindings/signatures.dart b/lib/src/bindings/signatures.dart index 1a0b47aa..bbf0dc7c 100644 --- a/lib/src/bindings/signatures.dart +++ b/lib/src/bindings/signatures.dart @@ -4,7 +4,6 @@ import 'structs.dart'; // common functions typedef obx_version_native_t = Void Function(Pointer major, Pointer minor, Pointer patch); typedef obx_version_string_native_t = Pointer Function(); -typedef obx_free_t = Void Function(Pointer ptr); typedef obx_free_struct_native_t = Void Function(Pointer structPtr); // error info diff --git a/lib/src/query/query.dart b/lib/src/query/query.dart index d4aa76e6..6dfcd87c 100644 --- a/lib/src/query/query.dart +++ b/lib/src/query/query.dart @@ -551,7 +551,7 @@ class Query { OBX_id_array idArray = idArrayPtr.ref; return idArray.length == 0 ? List() : idArray.items(); } finally { - bindings.obx_id_array_free(idArrayPtr); + bindings.obx_id_array_free(idArrayPtr.cast()); } } From 2cad3699d83b70e9d90b7d5662d1b3fc2357b380 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Fri, 25 Oct 2019 19:33:31 +0200 Subject: [PATCH 08/10] fixed utf8 frees, not 100% sure this is correct, since there is no clear connection between the alloc of Uint8 and the Utf8 Struct At least we can generate, compile, run all the tests --- lib/src/common.dart | 2 +- lib/src/query/query.dart | 11 +++++++---- objectbox-model.json | 20 +++++++++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/src/common.dart b/lib/src/common.dart index d874df7d..96b91a86 100644 --- a/lib/src/common.dart +++ b/lib/src/common.dart @@ -1,5 +1,5 @@ import "dart:ffi"; -import "package:ffi/ffi.dart" show allocate, free; +import "package:ffi/ffi.dart" show allocate, free, Utf8; import "bindings/bindings.dart"; diff --git a/lib/src/query/query.dart b/lib/src/query/query.dart index 6dfcd87c..eb62f3ac 100644 --- a/lib/src/query/query.dart +++ b/lib/src/query/query.dart @@ -276,11 +276,13 @@ class StringCondition extends PropertyCondition { int _op1(QueryBuilder builder, obx_qb_cond_string_op_1_dart_t func) { final utf8Str = Utf8.toUtf8(_value); + var uint8Str = utf8Str.cast(); try { - var uint8Str = utf8Str.cast(); + return func(builder._cBuilder, _property._propertyId, uint8Str, _caseSensitive ? 1 : 0); } finally { - utf8Str.free(); + // https://github.com/dart-lang/ffi/blob/master/lib/src/utf8.dart#L56 + free(utf8Str); } } @@ -305,11 +307,12 @@ class StringCondition extends PropertyCondition { int _opWithEqual(QueryBuilder builder, obx_qb_string_lt_gt_op_dart_t func) { final utf8Str = Utf8.toUtf8(_value); + var uint8Str = utf8Str.cast(); try { - var uint8Str = utf8Str.cast(); + return func(builder._cBuilder, _property._propertyId, uint8Str, _caseSensitive ? 1 : 0, _withEqual ? 1 : 0); } finally { - utf8Str.free(); + free(utf8Str); } } diff --git a/objectbox-model.json b/objectbox-model.json index 759f37bf..30d8ead3 100644 --- a/objectbox-model.json +++ b/objectbox-model.json @@ -93,9 +93,27 @@ "type": 2 } ] + }, + { + "id": "3:2896129536175217037", + "lastPropertyId": "2:8763914271730887369", + "name": "Note", + "properties": [ + { + "id": "1:5413230481051213381", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:8763914271730887369", + "name": "text", + "type": 9 + } + ] } ], - "lastEntityId": "2:2679953000475642792", + "lastEntityId": "3:2896129536175217037", "lastIndexId": "0:0", "lastRelationId": "0:0", "lastSequenceId": "0:0", From 171b52e5017460815ac69f1e24deb0d0ec81b377 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Wed, 6 Nov 2019 11:25:43 +0100 Subject: [PATCH 09/10] corrected/updated README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c24f9798..5ba72f88 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Proceed based on whether you're developing a Flutter app or a standalone dart pr * macOS: if dart later complains that it cannot find the `libobjectbox.dylib` you probably have to unsign the `dart` binary (source: [dart issue](https://github.com/dart-lang/sdk/issues/38314#issuecomment-534102841)): ```shell script - sudo xcode --remove-signature $(which dart) + sudo codesign --remove-signature $(which dart) ``` * Windows: use "Git Bash" or similar to execute the following command ```shell script @@ -111,8 +111,8 @@ queryNullText.close(); // We have to manually close queries and query builders. ``` More complex queries can be constructed using `and/or` operators. -Also there is basic operator overloading support for `equal`, `greater`, `less`, `and` and `or`, -respectively `==`, `>`, `<`, `&`, `|`. +Also there is basic operator overloading support for `greater`, `less`, `and` and `or`, +respectively `>`, `<`, `&`, `|`. ```dart // final box ... From 3d4cd72b159eafe2b6925bc65045118de6566eb3 Mon Sep 17 00:00:00 2001 From: Jasm Sison Date: Wed, 6 Nov 2019 15:10:17 +0100 Subject: [PATCH 10/10] fixed examples --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5ba72f88..35b826ca 100644 --- a/README.md +++ b/README.md @@ -117,11 +117,11 @@ respectively `>`, `<`, `&`, `|`. ```dart // final box ... -box.query(value.greaterThan(10).or(date.IsNull())).build(); +box.query(value.greaterThan(10).or(date.isNull())).build(); // equivalent to -final overloaded = (value > 10) | date.IsNull(); +final overloaded = (value > 10) | date.isNull(); box.query(overloaded as Condition).build(); // the cast is necessary due to the type analyzer ``` @@ -137,7 +137,7 @@ final q = box.query(Entity_.number > 0) // ... final qt = box.query(Entity_.text.notNull()) - .order(Entity_.text, flags: OBXOrderFlag.DESCENDING | OBXOrderFlag.CASE_SENSITIVE) + .order(Entity_.text, flags: Order.descending | Order.caseSensitive) .build(); ```