func doFinish(call rpc.ClientCall, numResults int) (C.SwiftByteArrayArray, error) { // Have all the results be decoded into *vdl.Value. resultPtrs := make([]interface{}, numResults) for i := 0; i < numResults; i++ { value := new(vdl.Value) resultPtrs[i] = &value } if err := call.Finish(resultPtrs...); err != nil { // Invocation error. return EmptySwiftByteArrayArray(), err } // VOM-encode the results. Note in the future we'll want a pathway where we can get the original VOM results // from finish so we don't end up wasting CPU & memory here. // Prepare the byte array array that can be accessed from Swift via C.malloc vomResultsMemory := C.malloc(C.size_t(numResults * int(C.sizeofSwiftByteArray))) // Make that malloc'd memory available as a slice to Go. vomResultsPtrsHdr := reflect.SliceHeader{ Data: uintptr(vomResultsMemory), Len: numResults, Cap: numResults, } vomResults := *(*[]C.SwiftByteArray)(unsafe.Pointer(&vomResultsPtrsHdr)) // Create the C Struct to return that encapsulates our byte array array var cVomResults C.SwiftByteArrayArray cVomResults.length = C._GoUint64(numResults) cVomResults.data = (*C.SwiftByteArray)(vomResultsMemory) // For each result, VOM encode into a byte array that we stick into the returned struct for i, resultPtr := range resultPtrs { // Remove the pointer from the result. Simply *resultPtr doesn't work // as resultPtr is of type interface{}. result := interface{}(sutil.DerefOrDie(resultPtr)) var vomResult []byte var err error if vomResult, err = vom.Encode(result); err != nil { return EmptySwiftByteArrayArray(), err } cVomResultCopy := C.malloc(C.size_t(len(vomResult))) C.memcpy(cVomResultCopy, unsafe.Pointer(&vomResult[0]), C.size_t(len(vomResult))) var cVomResult C.SwiftByteArray cVomResult.length = C._GoUint64(len(vomResult)) cVomResult.data = cVomResultCopy vomResults[i] = cVomResult } return cVomResults, nil }
func EmptySwiftByteArrayArray() C.SwiftByteArrayArray { var empty C.SwiftByteArrayArray empty.length = 0 empty.data = nil return empty }