func Curves(basis string, spans []int, wrap string, varargs ...interface{}) { pBasis := C.CString(basis) defer C.free(unsafe.Pointer(pBasis)) pWrap := C.CString(wrap) defer C.free(unsafe.Pointer(pWrap)) names, values, ownership := unzipArgs(varargs...) defer freeArgs(names, ownership) nArgs := C.RtInt(len(varargs) / 2) nSpans := C.RtInt(len(spans)) pSpans := (*C.RtInt)(C.RtPointer(&spans[0])) pNames, pVals := safeArgs(names, values) C.RiCurvesV(pBasis, nSpans, pSpans, pWrap, nArgs, pNames, pVals) }
func unzipArgs(varargs ...interface{}) (names rtTokens, vals rtPointers, owned rawPointers) { if len(varargs)%2 != 0 { fmt.Println("odd number of arguments") return } nArgs := len(varargs) / 2 names = make(rtTokens, nArgs) vals = make(rtPointers, nArgs) owned = make(rawPointers, nArgs) var pname string for i, v := range varargs { // Even-numbered arguments are parameter names if i%2 == 0 { if stringified, ok := v.(string); ok { pname = stringified token := C.CString(pname) names[i/2] = token } else { fmt.Printf("argument %d is not a string\n", i) return } continue } // Odd-numbered arguments are values switch v.(type) { case bool: boolified := v.(bool) var intified int32 = 0 if boolified { intified = 1 } vals[i/2] = C.RtPointer(&intified) case int, int32: intified := v.(int) vals[i/2] = C.RtPointer(&intified) case [3]float32: floatified := v.([3]float32) vals[i/2] = C.RtPointer(&floatified[0]) case [4]float32: floatified := v.([4]float32) vals[i/2] = C.RtPointer(&floatified[0]) case []float32: floatified := v.([]float32) vals[i/2] = C.RtPointer(&floatified[0]) case float32: floatified := v.(float32) vals[i/2] = C.RtPointer(&floatified) case float64: floatified := float32(v.(float64)) vals[i/2] = C.RtPointer(&floatified) case string: stringified := v.(string) token := C.CString(stringified) vals[i/2] = C.RtPointer(&token) owned[i/2] = unsafe.Pointer(token) default: m := fmt.Sprintf("'%s' has unknown type %T\n", pname, v) panic(m) } } return }