diff options
| author | Teddy Wing | 2020-03-11 00:00:22 +0100 | 
|---|---|---|
| committer | Teddy Wing | 2020-03-11 00:44:31 +0100 | 
| commit | 5e1b28caa8d81dee0e9ac7b29fe5621259e15e50 (patch) | |
| tree | 3e926ef822feaba5232ef6cd5c4752da209d0f1a | |
| parent | 428fb6dcab1377dd887d65eb2a496f6d5bbe1b6c (diff) | |
| download | go-notifier-5e1b28caa8d81dee0e9ac7b29fe5621259e15e50.tar.bz2 | |
Correct macOS >= 10.13, Go >= 1.10 CoreFoundation pointer type errorsupdate-to-build-against-go1.14
When building the project on macOS 10.15 with Go 1.13, I ended up with
the following errors:
    # github.com/keybase/go-notifier
    ./corefoundation.go:25:9: cannot convert nil to type _Ctype_CFTypeRef
    ./corefoundation.go:34:3: cannot use nil as type _Ctype_CFDataRef in return argument
    ./corefoundation.go:40:26: cannot use nil as type _Ctype_CFAllocatorRef in argument to _Cfunc_CFDataCreate
    ./corefoundation.go:41:12: cannot convert nil to type _Ctype_CFDataRef
    ./corefoundation.go:42:3: cannot use nil as type _Ctype_CFDataRef in return argument
    ./corefoundation.go:66:47: cannot use nil as type _Ctype_CFAllocatorRef in assignment
    ./corefoundation.go:67:12: cannot convert nil to type _Ctype_CFDictionaryRef
    ./corefoundation.go:68:3: cannot use nil as type _Ctype_CFDictionaryRef in return argument
    ./corefoundation.go:79:59: cannot convert &(*_cgoIndex1)[0] (type *_Ctype_CFTypeRef) to type *unsafe.Pointer
    ./corefoundation.go:79:88: cannot convert &(*_cgoIndex2)[0] (type *_Ctype_CFTypeRef) to type *unsafe.Pointer
    ./corefoundation.go:92:3: cannot use nil as type _Ctype_CFStringRef in return argument
    ./corefoundation.go:95:3: cannot use nil as type _Ctype_CFStringRef in return argument
    ./corefoundation.go:103:34: cannot use nil as type _Ctype_CFAllocatorRef in argument to _Cfunc_CFStringCreateWithBytes
    ./corefoundation.go:138:39: cannot use nil as type _Ctype_CFAllocatorRef in assignment
    ./corefoundation.go:146:69: cannot convert &(*_cgoIndex2)[0] (type *_Ctype_CFTypeRef) to type *unsafe.Pointer
    ./corefoundation.go:157:4: cannot use nil as type _Ctype_CFArrayRef in return argument
    ./corefoundation.go:178:4: cannot use nil as type _Ctype_CFDictionaryRef in return argument
    ./corefoundation.go:190:5: cannot use nil as type _Ctype_CFDictionaryRef in return argument
    ./corefoundation.go:197:5: cannot use nil as type _Ctype_CFDictionaryRef in return argument
    ./corefoundation.go:204:5: cannot use nil as type _Ctype_CFDictionaryRef in return argument
    ./corefoundation.go:211:4: cannot use nil as type _Ctype_CFDictionaryRef in return argument
    ./corefoundation.go:218:3: cannot use nil as type _Ctype_CFDictionaryRef in return argument
    ./notifier_darwin.go:57:38: cannot use nil as type _Ctype_CFStringRef in assignment
    ./notifier_darwin.go:58:3: cannot use nil as type _Ctype_CFStringRef in assignment
Found similar errors reported on the 'fsevents' project:
https://github.com/fsnotify/fsevents/issues/33 ,
https://github.com/golang/go/issues/23317
It turns out that Cgo handles CoreFoundation types differently starting
in Go 1.10:
> Cgo now translates some C types that would normally map to a pointer
> type in Go, to a uintptr instead. These types include the CFTypeRef
> hierarchy in Darwin's CoreFoundation framework and the jobject
> hierarchy in Java's JNI interface.
>
> These types must be uintptr on the Go side because they would
> otherwise confuse the Go garbage collector; they are sometimes not
> really pointers but data structures encoded in a pointer-sized
> integer. Pointers to Go memory must not be stored in these uintptr
> values.
>
> Because of this change, values of the affected types need to be
> zero-initialized with the constant 0 instead of the constant nil.
https://tip.golang.org/doc/go1.10#cgo
For the "cannot convert" errors, use xlab's (https://github.com/xlab)
suggestion:
> The workaround is to pass it as ptr :=
> (*unsafe.Pointer)(unsafe.Pointer(arg)) which looks strange but works.
https://github.com/golang/go/issues/13830#issuecomment-169139332
| -rw-r--r-- | corefoundation.go | 42 | ||||
| -rw-r--r-- | notifier_darwin.go | 4 | 
2 files changed, 23 insertions, 23 deletions
| diff --git a/corefoundation.go b/corefoundation.go index ebec7a4..9f0bbff 100644 --- a/corefoundation.go +++ b/corefoundation.go @@ -22,7 +22,7 @@ import (  // Release releases a TypeRef  func Release(ref C.CFTypeRef) { -	if ref != nil { +	if ref != 0 {  		C.CFRelease(ref)  	}  } @@ -31,15 +31,15 @@ func Release(ref C.CFTypeRef) {  // Release(ref).  func BytesToCFData(b []byte) (C.CFDataRef, error) {  	if uint64(len(b)) > math.MaxUint32 { -		return nil, fmt.Errorf("Data is too large") +		return 0, fmt.Errorf("Data is too large")  	}  	var p *C.UInt8  	if len(b) > 0 {  		p = (*C.UInt8)(&b[0])  	} -	cfData := C.CFDataCreate(nil, p, C.CFIndex(len(b))) -	if cfData == nil { -		return nil, fmt.Errorf("CFDataCreate failed") +	cfData := C.CFDataCreate(0, p, C.CFIndex(len(b))) +	if cfData == 0 { +		return 0, fmt.Errorf("CFDataCreate failed")  	}  	return cfData, nil  } @@ -63,9 +63,9 @@ func MapToCFDictionary(m map[C.CFTypeRef]C.CFTypeRef) (C.CFDictionaryRef, error)  		keysPointer = &keys[0]  		valuesPointer = &values[0]  	} -	cfDict := C.CFDictionaryCreate(nil, keysPointer, valuesPointer, C.CFIndex(numValues), &C.kCFTypeDictionaryKeyCallBacks, &C.kCFTypeDictionaryValueCallBacks) -	if cfDict == nil { -		return nil, fmt.Errorf("CFDictionaryCreate failed") +	cfDict := C.CFDictionaryCreate(0, keysPointer, valuesPointer, C.CFIndex(numValues), &C.kCFTypeDictionaryKeyCallBacks, &C.kCFTypeDictionaryValueCallBacks) +	if cfDict == 0 { +		return 0, fmt.Errorf("CFDictionaryCreate failed")  	}  	return cfDict, nil  } @@ -76,7 +76,7 @@ func CFDictionaryToMap(cfDict C.CFDictionaryRef) (m map[C.CFTypeRef]C.CFTypeRef)  	if count > 0 {  		keys := make([]C.CFTypeRef, count)  		values := make([]C.CFTypeRef, count) -		C.CFDictionaryGetKeysAndValues(cfDict, (*unsafe.Pointer)(&keys[0]), (*unsafe.Pointer)(&values[0])) +		C.CFDictionaryGetKeysAndValues(cfDict, (*unsafe.Pointer)(unsafe.Pointer(keys[0])), (*unsafe.Pointer)(unsafe.Pointer(values[0])))  		m = make(map[C.CFTypeRef]C.CFTypeRef, count)  		for i := C.CFIndex(0); i < count; i++ {  			m[keys[i]] = values[i] @@ -89,10 +89,10 @@ func CFDictionaryToMap(cfDict C.CFDictionaryRef) (m map[C.CFTypeRef]C.CFTypeRef)  // Release(ref).  func StringToCFString(s string) (C.CFStringRef, error) {  	if !utf8.ValidString(s) { -		return nil, errors.New("Invalid UTF-8 string") +		return 0, errors.New("Invalid UTF-8 string")  	}  	if uint64(len(s)) > math.MaxUint32 { -		return nil, errors.New("String is too large") +		return 0, errors.New("String is too large")  	}  	bytes := []byte(s) @@ -100,7 +100,7 @@ func StringToCFString(s string) (C.CFStringRef, error) {  	if len(bytes) > 0 {  		p = (*C.UInt8)(&bytes[0])  	} -	return C.CFStringCreateWithBytes(nil, p, C.CFIndex(len(s)), C.kCFStringEncodingUTF8, C.false), nil +	return C.CFStringCreateWithBytes(0, p, C.CFIndex(len(s)), C.kCFStringEncodingUTF8, C.false), nil  }  // CFStringToString converts a CFStringRef to a string. @@ -135,7 +135,7 @@ func ArrayToCFArray(a []C.CFTypeRef) C.CFArrayRef {  	if numValues > 0 {  		valuesPointer = &values[0]  	} -	return C.CFArrayCreate(nil, valuesPointer, C.CFIndex(numValues), &C.kCFTypeArrayCallBacks) +	return C.CFArrayCreate(0, valuesPointer, C.CFIndex(numValues), &C.kCFTypeArrayCallBacks)  }  // CFArrayToArray converts a CFArrayRef to an array of CFTypes. @@ -143,7 +143,7 @@ func CFArrayToArray(cfArray C.CFArrayRef) (a []C.CFTypeRef) {  	count := C.CFArrayGetCount(cfArray)  	if count > 0 {  		a = make([]C.CFTypeRef, count) -		C.CFArrayGetValues(cfArray, C.CFRange{0, count}, (*unsafe.Pointer)(&a[0])) +		C.CFArrayGetValues(cfArray, C.CFRange{0, count}, (*unsafe.Pointer)(unsafe.Pointer(a[0])))  	}  	return  } @@ -154,7 +154,7 @@ func StringsToCFArray(strs []string) C.CFArrayRef {  	for _, s := range strs {  		strRef, err := StringToCFString(s)  		if err != nil { -			return nil +			return 0  		}  		defer Release(C.CFTypeRef(strRef))  		strRefs = append(strRefs, C.CFTypeRef(strRef)) @@ -175,7 +175,7 @@ func ConvertMapToCFDictionary(attr map[string]interface{}) (C.CFDictionaryRef, e  		var valueRef C.CFTypeRef  		switch i.(type) {  		default: -			return nil, fmt.Errorf("Unsupported value type: %v", reflect.TypeOf(i)) +			return 0, fmt.Errorf("Unsupported value type: %v", reflect.TypeOf(i))  		case C.CFTypeRef:  			valueRef = i.(C.CFTypeRef)  		case bool: @@ -187,35 +187,35 @@ func ConvertMapToCFDictionary(attr map[string]interface{}) (C.CFDictionaryRef, e  		case []byte:  			bytesRef, err := BytesToCFData(i.([]byte))  			if err != nil { -				return nil, err +				return 0, err  			}  			valueRef = C.CFTypeRef(bytesRef)  			defer Release(valueRef)  		case string:  			stringRef, err := StringToCFString(i.(string))  			if err != nil { -				return nil, err +				return 0, err  			}  			valueRef = C.CFTypeRef(stringRef)  			defer Release(valueRef)  		case Convertable:  			convertedRef, err := (i.(Convertable)).Convert()  			if err != nil { -				return nil, err +				return 0, err  			}  			valueRef = C.CFTypeRef(convertedRef)  			defer Release(valueRef)  		}  		keyRef, err := StringToCFString(key)  		if err != nil { -			return nil, err +			return 0, err  		}  		m[C.CFTypeRef(keyRef)] = valueRef  	}  	cfDict, err := MapToCFDictionary(m)  	if err != nil { -		return nil, err +		return 0, err  	}  	return cfDict, nil  } diff --git a/notifier_darwin.go b/notifier_darwin.go index e6f9c07..45d61f0 100644 --- a/notifier_darwin.go +++ b/notifier_darwin.go @@ -54,8 +54,8 @@ func (n darwinNotifier) DeliverNotification(notification Notification) error {  	actionsRef := StringsToCFArray(notification.Actions)  	defer Release(C.CFTypeRef(actionsRef)) -	C.deliverNotification(titleRef, nil, messageRef, appIconURLStringRef, actionsRef, -		bundleIDRef, nil, C.NSTimeInterval(notification.Timeout), false) +	C.deliverNotification(titleRef, 0, messageRef, appIconURLStringRef, actionsRef, +		bundleIDRef, 0, C.NSTimeInterval(notification.Timeout), false)  	return nil  } | 
