Fix handling of id and void* types. Add helper functions to convert
char* to and from Go strings. Parse block (^) types. Skip methods with functions as parameters. Fix passing pointers go C code.
This commit is contained in:
parent
98e19ca726
commit
4f260dda0e
2
main.go
2
main.go
|
@ -212,7 +212,7 @@ func Start(args ProgramArgs) (err error) {
|
||||||
w.AddCategory(x)
|
w.AddCategory(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Wrap([]string{"ClassOne"})
|
w.Wrap([]string{"NSString"})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,9 @@ func NewType(n *Node, c string) *Type {
|
||||||
|
|
||||||
func NewTypeFromString(t,c string) *Type {
|
func NewTypeFromString(t,c string) *Type {
|
||||||
n,err := Parse(t)
|
n,err := Parse(t)
|
||||||
|
if n.CtypeSimplified() == "id" {
|
||||||
|
n,err = Parse("NSObject*")
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Type{}
|
return &Type{}
|
||||||
}
|
}
|
||||||
|
@ -56,12 +59,12 @@ func (t *Type) String() string {
|
||||||
return t.Node.String()
|
return t.Node.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) Wrap() {
|
func Wrap(s string) {
|
||||||
if wrapped == nil {
|
if wrapped == nil {
|
||||||
wrapped = make(map[string]bool)
|
wrapped = make(map[string]bool)
|
||||||
}
|
}
|
||||||
// it is the pointers to this type that get wrapped
|
// it is the pointers to this type that get wrapped
|
||||||
wrapped["*" + t.GoType()] = true
|
wrapped["*" + s] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) BaseType() *Type {
|
func (t *Type) BaseType() *Type {
|
||||||
|
@ -85,6 +88,9 @@ func swapstars(s string) string {
|
||||||
func (t *Type) CGoType() string {
|
func (t *Type) CGoType() string {
|
||||||
ct := swapstars("C." + t.CType())
|
ct := swapstars("C." + t.CType())
|
||||||
ct = strings.ReplaceAll(ct," ","_")
|
ct = strings.ReplaceAll(ct," ","_")
|
||||||
|
if ct == "C.long_long" {
|
||||||
|
ct = "C.long" // FIXME why?
|
||||||
|
}
|
||||||
return ct
|
return ct
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,29 +130,30 @@ func (t *Type) GoTypeDecl() string {
|
||||||
return t.GoInterfaceDecl()
|
return t.GoInterfaceDecl()
|
||||||
}
|
}
|
||||||
tp := t.BaseType()
|
tp := t.BaseType()
|
||||||
return fmt.Sprintf(`
|
gt := tp.GoType()
|
||||||
|
switch gt {
|
||||||
|
case "", "Void":
|
||||||
|
return ""
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf(`
|
||||||
type %s %s
|
type %s %s
|
||||||
`,tp.GoType(),tp.CGoType())
|
`,gt,tp.CGoType())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) GoInterfaceDecl() string {
|
func (t *Type) GoInterfaceDecl() string {
|
||||||
return _goInterfaceDecl(t.GoType())
|
gt := t.GoType()
|
||||||
}
|
if gt[0] == '*' {
|
||||||
|
gt = gt[1:] // dereference wrapped types
|
||||||
func _goInterfaceDecl(c string) string {
|
|
||||||
if c[0] == '*' {
|
|
||||||
c = c[1:] // dereference wrapped types
|
|
||||||
}
|
}
|
||||||
x := ""
|
x := ""
|
||||||
super := Super(c)
|
super := Super(gt)
|
||||||
if super == "" {
|
if super == "" {
|
||||||
super = "ptr unsafe.Pointer"
|
super = "ptr unsafe.Pointer"
|
||||||
} else {
|
|
||||||
x = _goInterfaceDecl(super) + "\n"
|
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
%stype %s struct { %s }
|
%stype %s struct { %s }
|
||||||
`,x,c,super)
|
`,x,gt,super)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) CToGo(cval string) string { // cast C value to CGo
|
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()] {
|
if wrapped[pt.GoType()] {
|
||||||
p = pn + ".ptr"
|
p = pn + ".ptr"
|
||||||
} else {
|
} else {
|
||||||
p = "(" + pt.CGoType() + ")(" + pn + ")"
|
if pt.Node.IsPointer() {
|
||||||
|
p = "unsafe.Pointer(" + pn + ")"
|
||||||
|
} else {
|
||||||
|
p = "(" + pt.CGoType() + ")(" + pn + ")"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parms = append(parms,p)
|
parms = append(parms,p)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ func AbstractDeclarator(s string, n *Node) (string, *Node) {
|
||||||
Opt(Pointer),
|
Opt(Pointer),
|
||||||
OneOrMore(DirectAbstractDeclarator)),
|
OneOrMore(DirectAbstractDeclarator)),
|
||||||
Pointer,
|
Pointer,
|
||||||
|
Block,
|
||||||
)(s,n)
|
)(s,n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +135,7 @@ func NullableAnnotation(s string, n *Node) (string, *Node) {
|
||||||
Word("_Null_unspecified"),
|
Word("_Null_unspecified"),
|
||||||
))(s,n)
|
))(s,n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pointer(s string, n *Node) (string, *Node) {
|
func Pointer(s string, n *Node) (string, *Node) {
|
||||||
return Seq(
|
return Seq(
|
||||||
NodeNamed("Pointer",Lit("*")),
|
NodeNamed("Pointer",Lit("*")),
|
||||||
|
@ -143,6 +145,14 @@ func Pointer(s string, n *Node) (string, *Node) {
|
||||||
)(s,n)
|
)(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) {
|
func TypeQualifierList(s string, n *Node) (string, *Node) {
|
||||||
return OneOrMore(TypeQualifier)(s,n)
|
return OneOrMore(TypeQualifier)(s,n)
|
||||||
}
|
}
|
||||||
|
|
83
wrap/main.go
83
wrap/main.go
|
@ -26,9 +26,10 @@ type Wrapper struct {
|
||||||
goStructTypes map[string]cStruct // map from gotype to struct descr.
|
goStructTypes map[string]cStruct // map from gotype to struct descr.
|
||||||
goInterfaceTypes []string
|
goInterfaceTypes []string
|
||||||
|
|
||||||
cCode strings.Builder // put cGo code here
|
cCode strings.Builder // put cGo code here
|
||||||
goTypes strings.Builder // put Go type declarations here
|
goTypes strings.Builder // put Go type declarations here
|
||||||
goCode strings.Builder // put Go code here
|
goCode strings.Builder // put Go code here
|
||||||
|
goHelpers strings.Builder // put Go helper functions here
|
||||||
Processed map[string]bool
|
Processed map[string]bool
|
||||||
Processed2 map[string]bool
|
Processed2 map[string]bool
|
||||||
}
|
}
|
||||||
|
@ -191,6 +192,16 @@ func (m Method) isVoid() bool {
|
||||||
return m.Type == "void"
|
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
|
func (w Wrapper) isObject(tp string) bool { // takes a goType
|
||||||
if _,ok := w.Interfaces[tp]; ok {
|
if _,ok := w.Interfaces[tp]; ok {
|
||||||
return true
|
return true
|
||||||
|
@ -204,11 +215,11 @@ func (w Wrapper) cparamlist(m Method) string {
|
||||||
ret = append(ret,"void* obj")
|
ret = append(ret,"void* obj")
|
||||||
}
|
}
|
||||||
for _,p := range m.Parameters {
|
for _,p := range m.Parameters {
|
||||||
tp := p.Type
|
var tp string
|
||||||
gtp := w.goType(tp,m.Class)
|
if p.Tp.Node.IsPointer() {
|
||||||
//w.goType(tp,m.Class)
|
|
||||||
if w.isObject(gtp) {
|
|
||||||
tp = "void*"
|
tp = "void*"
|
||||||
|
} else {
|
||||||
|
tp = p.Tp.CType()
|
||||||
}
|
}
|
||||||
ret = append(ret,fmt.Sprintf("%s %s",tp,p.Vname))
|
ret = append(ret,fmt.Sprintf("%s %s",tp,p.Vname))
|
||||||
}
|
}
|
||||||
|
@ -257,7 +268,11 @@ func (m *Method) gpntp() ([]string,[]*types.Type,string) {
|
||||||
i := 0
|
i := 0
|
||||||
if !m.ClassMethod { i = 1 }
|
if !m.ClassMethod { i = 1 }
|
||||||
for ; i < len(ns); i++ {
|
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,", ")
|
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?
|
w.AddType(name,name) // need this?
|
||||||
}
|
}
|
||||||
tp := types.NewTypeFromString(name,name)
|
tp := types.NewTypeFromString(name,name)
|
||||||
tp.Wrap()
|
types.Wrap(tp.GoType())
|
||||||
var avail bool
|
var avail bool
|
||||||
for _,c := range ns {
|
for _,c := range ns {
|
||||||
switch x := c.(type) {
|
switch x := c.(type) {
|
||||||
|
@ -477,20 +492,48 @@ func (w *Wrapper) pt2(tps ...*types.Type) {
|
||||||
case 0:
|
case 0:
|
||||||
return
|
return
|
||||||
case 1:
|
case 1:
|
||||||
break
|
w._pt2(tps[0])
|
||||||
default:
|
default:
|
||||||
for _,tp := range tps {
|
for _,tp := range tps {
|
||||||
w.pt2(tp)
|
w.pt2(tp)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tp := tps[0].BaseType()
|
}
|
||||||
if w.Processed2[tp.GoType()] { return }
|
|
||||||
w.Processed2[tp.GoType()] = true
|
func (w *Wrapper) _pt2(tp *types.Type) {
|
||||||
if tp.Node.IsFunction() {
|
bt := tp.BaseType()
|
||||||
|
if w.Processed2[bt.GoType()] { return }
|
||||||
|
w.Processed2[bt.GoType()] = true
|
||||||
|
if bt.Node.IsFunction() {
|
||||||
return
|
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) {
|
func (w *Wrapper) ProcessType(gotype string) {
|
||||||
|
@ -596,6 +639,9 @@ New%s() {
|
||||||
if m.Tp.Node.IsFunction() {
|
if m.Tp.Node.IsFunction() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if m.hasFunctionParam() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
gname := strings.Title(m.Name)
|
gname := strings.Title(m.Name)
|
||||||
cname := i.Name + "_" + m.Name
|
cname := i.Name + "_" + m.Name
|
||||||
|
|
||||||
|
@ -605,9 +651,13 @@ New%s() {
|
||||||
ns,tps,gplist := m.gpntp()
|
ns,tps,gplist := m.gpntp()
|
||||||
w.pt2(tps...)
|
w.pt2(tps...)
|
||||||
w.pt2(m.Tp)
|
w.pt2(m.Tp)
|
||||||
|
grtype := m.Tp.GoType()
|
||||||
|
if grtype == "Void" {
|
||||||
|
grtype = ""
|
||||||
|
}
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func (o *%s) %s(%s) %s {
|
func (o *%s) %s(%s) %s {
|
||||||
`,i.Name,gname,gplist,m.Tp.GoType()))
|
`,i.Name,gname,gplist,grtype))
|
||||||
w.goCode.WriteString(
|
w.goCode.WriteString(
|
||||||
types.GoToC(cname,ns,m.Tp,tps) + "}\n\n")
|
types.GoToC(cname,ns,m.Tp,tps) + "}\n\n")
|
||||||
|
|
||||||
|
@ -640,5 +690,6 @@ import (
|
||||||
)
|
)
|
||||||
`)
|
`)
|
||||||
fmt.Println(w.goTypes.String())
|
fmt.Println(w.goTypes.String())
|
||||||
|
fmt.Println(w.goHelpers.String())
|
||||||
fmt.Println(w.goCode.String())
|
fmt.Println(w.goCode.String())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user