// AddOperation adds an operation to g. func (g *Graph) AddOperation(args OpSpec) (*Operation, error) { if args.Name == "" { args.Name = args.Type } cname := C.CString(args.Name) ctype := C.CString(args.Type) cdesc := C.TF_NewOperation(g.c, ctype, cname) C.free(unsafe.Pointer(cname)) C.free(unsafe.Pointer(ctype)) for _, in := range args.Input { switch in := in.(type) { case Output: C.TF_AddInput(cdesc, in.c()) case OutputList: size := len(in) list := make([]C.TF_Output, size) for i, v := range in { list[i] = v.c() } C.TF_AddInputList(cdesc, &list[0], C.int(size)) } } status := newStatus() for name, value := range args.Attrs { if err := setAttr(cdesc, status, name, value); err != nil { // Memory leak here as the TF_OperationDescription // object will not be cleaned up. At the time of this // writing, this was next to impossible since it // required value to be a string tensor with // incorrectly encoded strings. Given this rarity, live // with the memory leak. If it becomes a real problem, // consider adding a TF_DeleteOperationDescription // function to the C API. return nil, fmt.Errorf("%v (memory will be leaked)", err) } } op := &Operation{ c: C.TF_FinishOperation(cdesc, status.c), g: g, } return op, status.Err() }
func (b *opBuilder) AddInput(port Output) { C.TF_AddInput(b.c, port.c()) }