// xpcToGo converts an xpc object to a go object // // note that not all the types are supported, but only the subset required for Blued func xpcToGo(v C.xpc_object_t) interface{} { t := C.xpc_get_type(v) switch t { case C.TYPE_ARRAY: a := make(Array, C.int(C.xpc_array_get_count(v))) C.XpcArrayApply(unsafe.Pointer(&a), v) return a case C.TYPE_DATA: return C.GoBytes(C.xpc_data_get_bytes_ptr(v), C.int(C.xpc_data_get_length(v))) case C.TYPE_DICT: d := make(Dict) C.XpcDictApply(unsafe.Pointer(&d), v) return d case C.TYPE_INT64: return int64(C.xpc_int64_get_value(v)) case C.TYPE_STRING: return C.GoString(C.xpc_string_get_string_ptr(v)) case C.TYPE_UUID: a := [16]byte{} C.XpcUUIDGetBytes(unsafe.Pointer(&a), v) return UUID(a[:]) default: log.Fatalf("unexpected type %#v, value %#v", t, v) } return nil }
//export handleXpcEvent func handleXpcEvent(event C.xpc_object_t, p unsafe.Pointer) { //log.Printf("handleXpcEvent %#v %#v\n", event, p) t := C.xpc_get_type(event) eh := *((*XpcEventHandler)(p)) if t == C.TYPE_ERROR { if event == C.ERROR_CONNECTION_INVALID { // The client process on the other end of the connection has either // crashed or cancelled the connection. After receiving this error, // the connection is in an invalid state, and you do not need to // call xpc_connection_cancel(). Just tear down any associated state // here. //log.Println("connection invalid") eh.HandleXpcEvent(nil, CONNECTION_INVALID) } else if event == C.ERROR_CONNECTION_INTERRUPTED { //log.Println("connection interrupted") eh.HandleXpcEvent(nil, CONNECTION_INTERRUPTED) } else if event == C.ERROR_CONNECTION_TERMINATED { // Handle per-connection termination cleanup. //log.Println("connection terminated") eh.HandleXpcEvent(nil, CONNECTION_TERMINATED) } else { //log.Println("got some error", event) eh.HandleXpcEvent(nil, fmt.Errorf("%v", event)) } } else { eh.HandleXpcEvent(xpcToGo(event).(Dict), nil) } }