objectbox-go
objectbox-go copied to clipboard
Fix bug in dataVisitorDispatch
The obx_data_visitor in ObjectBox Core (C library) is:
/// The callback for reading data one-by-one
/// @param data is the read data buffer
/// @param size specifies the length of the read data
/// @param user_data is a pass-through argument passed to the called API
/// @return true to keep going, false to cancel.
typedef bool obx_data_visitor(const void* data, size_t size, void* user_data);
// ...
/// Walk over matching objects using the given data visitor
OBX_C_API obx_err obx_query_visit(OBX_query* query, obx_data_visitor* visitor, void* user_data);
The first two parameter should be data and size according to the C header file, the third parameter is the user data.
But objectbox-go defined dataVisitorDispatch function in Go has a wrong parameter order:
// datavisitor.go
var dataVisitor = (*C.obx_data_visitor)(unsafe.Pointer(C.dataVisitorDispatch))
// datavisitorc.go
//export dataVisitorDispatch
// This function finds the data visitor (based on the pointer to the visitorId) and calls it with the given data
// NOTE: don't change ptr contents, it's `const void*` in C but go doesn't support const pointers
func dataVisitorDispatch(visitorIdPtr unsafe.Pointer, data unsafe.Pointer, size C.size_t) C.bool {
// ...
}
visitorIdPtr was passed as user data here:
// Find returns all objects matching the query
func (query *Query) Find() (objects interface{}, err error) {
defer runtime.KeepAlive(query)
if err := query.check(); err != nil {
return nil, err
}
const existingOnly = true
if supportsResultArray {
var cFn = func() *C.OBX_bytes_array {
return C.obx_query_find(query.cQuery)
}
return query.box.readManyObjects(existingOnly, cFn)
}
var cFn = func(visitorArg unsafe.Pointer) C.obx_err {
// visitorArg is passed as user data here
return C.obx_query_visit(query.cQuery, dataVisitor, visitorArg)
}
return query.box.readUsingVisitor(existingOnly, cFn)
}
This might lead to a crash when you use a ObjectBox Core C version without OBXFeature_ResultArray (e.g. Mobile version like iOS).
Simply re-order the parameter will fix this issue:
func dataVisitorDispatch(data unsafe.Pointer, size C.size_t, visitorIdPtr unsafe.Pointer) C.bool