diff --git a/main.go b/main.go index 0b177ae..788b0c4 100644 --- a/main.go +++ b/main.go @@ -212,7 +212,7 @@ func Start(args ProgramArgs) (err error) { w.AddCategory(x) } } - w.Wrap([]string{"ClassOne"}) + w.Wrap([]string{"NSString"}) return nil } diff --git a/types/convert.go b/types/convert.go index e9d5c93..8477b5c 100644 --- a/types/convert.go +++ b/types/convert.go @@ -42,6 +42,9 @@ func NewType(n *Node, c string) *Type { func NewTypeFromString(t,c string) *Type { n,err := Parse(t) + if n.CtypeSimplified() == "id" { + n,err = Parse("NSObject*") + } if err != nil { return &Type{} } @@ -56,12 +59,12 @@ func (t *Type) String() string { return t.Node.String() } -func (t *Type) Wrap() { +func Wrap(s string) { if wrapped == nil { wrapped = make(map[string]bool) } // it is the pointers to this type that get wrapped - wrapped["*" + t.GoType()] = true + wrapped["*" + s] = true } func (t *Type) BaseType() *Type { @@ -85,6 +88,9 @@ func swapstars(s string) string { func (t *Type) CGoType() string { ct := swapstars("C." + t.CType()) ct = strings.ReplaceAll(ct," ","_") + if ct == "C.long_long" { + ct = "C.long" // FIXME why? + } return ct } @@ -124,29 +130,30 @@ func (t *Type) GoTypeDecl() string { return t.GoInterfaceDecl() } tp := t.BaseType() - return fmt.Sprintf(` + gt := tp.GoType() + switch gt { + case "", "Void": + return "" + default: + return fmt.Sprintf(` type %s %s -`,tp.GoType(),tp.CGoType()) +`,gt,tp.CGoType()) + } } func (t *Type) GoInterfaceDecl() string { - return _goInterfaceDecl(t.GoType()) -} - -func _goInterfaceDecl(c string) string { - if c[0] == '*' { - c = c[1:] // dereference wrapped types + gt := t.GoType() + if gt[0] == '*' { + gt = gt[1:] // dereference wrapped types } x := "" - super := Super(c) + super := Super(gt) if super == "" { super = "ptr unsafe.Pointer" - } else { - x = _goInterfaceDecl(super) + "\n" } return fmt.Sprintf(` %stype %s struct { %s } -`,x,c,super) +`,x,gt,super) } func (t *Type) CToGo(cval string) string { // cast C value to CGo @@ -179,7 +186,11 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string { if wrapped[pt.GoType()] { p = pn + ".ptr" } else { - p = "(" + pt.CGoType() + ")(" + pn + ")" + if pt.Node.IsPointer() { + p = "unsafe.Pointer(" + pn + ")" + } else { + p = "(" + pt.CGoType() + ")(" + pn + ")" + } } parms = append(parms,p) } diff --git a/types/cparser.go b/types/cparser.go index 47e730f..d9ea9bd 100644 --- a/types/cparser.go +++ b/types/cparser.go @@ -30,6 +30,7 @@ func AbstractDeclarator(s string, n *Node) (string, *Node) { Opt(Pointer), OneOrMore(DirectAbstractDeclarator)), Pointer, + Block, )(s,n) } @@ -134,6 +135,7 @@ func NullableAnnotation(s string, n *Node) (string, *Node) { Word("_Null_unspecified"), ))(s,n) } + func Pointer(s string, n *Node) (string, *Node) { return Seq( NodeNamed("Pointer",Lit("*")), @@ -143,6 +145,14 @@ func Pointer(s string, n *Node) (string, *Node) { )(s,n) } +//FIXME: not sure how correct this is... +func Block(s string, n *Node) (string, *Node) { + return Seq( + NodeNamed("Block",Lit("^")), + Opt(NullableAnnotation), + )(s,n) +} + func TypeQualifierList(s string, n *Node) (string, *Node) { return OneOrMore(TypeQualifier)(s,n) } diff --git a/wrap/main.go b/wrap/main.go index a3c89e5..afae6d8 100644 --- a/wrap/main.go +++ b/wrap/main.go @@ -26,9 +26,10 @@ type Wrapper struct { goStructTypes map[string]cStruct // map from gotype to struct descr. goInterfaceTypes []string - cCode strings.Builder // put cGo code here - goTypes strings.Builder // put Go type declarations here - goCode strings.Builder // put Go code here + cCode strings.Builder // put cGo code here + goTypes strings.Builder // put Go type declarations here + goCode strings.Builder // put Go code here + goHelpers strings.Builder // put Go helper functions here Processed map[string]bool Processed2 map[string]bool } @@ -191,6 +192,16 @@ func (m Method) isVoid() bool { return m.Type == "void" } +//hasFunctionParam() returns true if a method has a function as a parameter. +func (m Method) hasFunctionParam() bool { + for _,p := range m.Parameters { + if p.Tp.Node.IsFunction() { + return true + } + } + return false +} + func (w Wrapper) isObject(tp string) bool { // takes a goType if _,ok := w.Interfaces[tp]; ok { return true @@ -204,11 +215,11 @@ func (w Wrapper) cparamlist(m Method) string { ret = append(ret,"void* obj") } for _,p := range m.Parameters { - tp := p.Type - gtp := w.goType(tp,m.Class) - //w.goType(tp,m.Class) - if w.isObject(gtp) { + var tp string + if p.Tp.Node.IsPointer() { tp = "void*" + } else { + tp = p.Tp.CType() } ret = append(ret,fmt.Sprintf("%s %s",tp,p.Vname)) } @@ -257,7 +268,11 @@ func (m *Method) gpntp() ([]string,[]*types.Type,string) { i := 0 if !m.ClassMethod { i = 1 } for ; i < len(ns); i++ { - ret = append(ret,ns[i] + " " + tps[i].GoType()) + gt := tps[i].GoType() + if gt == "*Void" { + gt = "unsafe.Pointer" + } + ret = append(ret,ns[i] + " " + gt) } return ns, tps, strings.Join(ret,", ") } @@ -363,7 +378,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) { w.AddType(name,name) // need this? } tp := types.NewTypeFromString(name,name) - tp.Wrap() + types.Wrap(tp.GoType()) var avail bool for _,c := range ns { switch x := c.(type) { @@ -477,20 +492,48 @@ func (w *Wrapper) pt2(tps ...*types.Type) { case 0: return case 1: - break + w._pt2(tps[0]) default: for _,tp := range tps { w.pt2(tp) } return } - tp := tps[0].BaseType() - if w.Processed2[tp.GoType()] { return } - w.Processed2[tp.GoType()] = true - if tp.Node.IsFunction() { +} + +func (w *Wrapper) _pt2(tp *types.Type) { + bt := tp.BaseType() + if w.Processed2[bt.GoType()] { return } + w.Processed2[bt.GoType()] = true + if bt.Node.IsFunction() { return } - w.goTypes.WriteString(tps[0].GoTypeDecl()) + w.goTypes.WriteString(tp.GoTypeDecl()) + if tp.GoType() == "*Char" { + w.CharHelpers() + } + super := types.Super(bt.GoType()) + if super != "" { + types.Wrap(super) + pt := types.NewTypeFromString(super + "*","") + w._pt2(pt) + } +} + +func (w *Wrapper) CharHelpers() { + w.goHelpers.WriteString(` +func CharFromString(s string) *Char { + return (*Char)(unsafe.Pointer(C.CString(s))) +} + +func CharFromBytes(b []byte) *Char { + return (*Char)(unsafe.Pointer(C.CString(string(b)))) +} + +func (c *Char) String() string { + return C.GoString((*C.char)(c)) +} +`) } func (w *Wrapper) ProcessType(gotype string) { @@ -596,6 +639,9 @@ New%s() { if m.Tp.Node.IsFunction() { continue } + if m.hasFunctionParam() { + continue + } gname := strings.Title(m.Name) cname := i.Name + "_" + m.Name @@ -605,9 +651,13 @@ New%s() { ns,tps,gplist := m.gpntp() w.pt2(tps...) w.pt2(m.Tp) + grtype := m.Tp.GoType() + if grtype == "Void" { + grtype = "" + } w.goCode.WriteString(fmt.Sprintf(` func (o *%s) %s(%s) %s { -`,i.Name,gname,gplist,m.Tp.GoType())) +`,i.Name,gname,gplist,grtype)) w.goCode.WriteString( types.GoToC(cname,ns,m.Tp,tps) + "}\n\n") @@ -640,5 +690,6 @@ import ( ) `) fmt.Println(w.goTypes.String()) + fmt.Println(w.goHelpers.String()) fmt.Println(w.goCode.String()) }