Make a Go Interface instead of a struct for top level objects.

Use a new struct Id as a concrete version of that type.
This commit is contained in:
Greg 2019-04-29 11:46:48 -04:00
parent c0c17e88d1
commit c03e37bd54
8 changed files with 94 additions and 19 deletions

2
.gitignore vendored
View File

@ -5,4 +5,4 @@ program
examples/foundation/foundation
examples/foundation/ns
examples/simple/simple
examples/simple/simple/ClassOne
examples/simple/ClassOne

View File

@ -0,0 +1,16 @@
package main
import (
"fmt"
"gitlab.wow.st/gmp/nswrap/examples/foundation/ns"
)
func main() {
n1 := ns.StringWithUTF8String(ns.CharFromString("hi there"))
c1 := n1.CapitalizedString()
gs := c1.UTF8String().String()
fmt.Println(gs)
a := ns.ArrayWithObjects(n1)
_ = a
}

View File

@ -18,5 +18,11 @@ struct stru {int a,b;};
- (int) hi2:(struct stru*)in;
- (struct stru) nstru1;
- (struct stru*) nstru2;
- (void) hi:(id)in;
- (void) hi3:(id)in;
@end
@interface ClassTwo : ClassOne
{ }
- (ClassTwo*) init;
@end

View File

@ -54,6 +54,19 @@
ret->b = 10;
return ret;
}
- (void) hi:(id)in
{
NSLog(@"hi");
}
- (void) hi3:(id)in
{
NSLog(@"hi");
}
@end
@implementation ClassTwo
- (ClassTwo*) init
{
return [super init];
}
@end

View File

@ -1,4 +1,4 @@
Package = "ClassOne"
InputFiles = [ "ClassOne/simple.h" ]
Classes = [ "ClassOne" ]
Classes = [ "ClassOne","ClassTwo" ]
Imports = [ "simple.h" ]

View File

@ -153,9 +153,9 @@ func Start() (err error) {
if err != nil {
// If clang fails it still prints out the AST, so we have to run it
// again to get the real error.
errBody, _ := exec.Command("clang", cargs...).CombinedOutput()
// errBody, _ := exec.Command("clang", cargs...).CombinedOutput()
panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
panic("clang failed: " + err.Error() + ":\n\n")
}
lines := readAST(astPP)

View File

@ -12,6 +12,26 @@ var super map[string]string
//go struct.
var wrapped map[string]bool
func shouldWrap(gt string) bool {
if wrapped == nil {
wrapped = make(map[string]bool)
return false
}
return gt != "" && gt[0] == '*' && wrapped[gt[1:]]
}
//goInterfaces records the names of top level Go interfaces. Pointers to these
//are dereferenced to bare interface names.
var goInterfaces map[string]bool
func isGoInterface(gt string) bool {
if goInterfaces == nil {
goInterfaces = make(map[string]bool)
return false
}
return goInterfaces[gt]
}
//TypeParameters maps, for each class, a TypedefName to a type, representing
//the Objective-C type parameters for that class
var TypeParameters map[string]map[string]string
@ -109,9 +129,6 @@ func (t *Type) BaseType() *Type {
t.Node.BaseType(),
t.Class,
)
// if ret.CType() == ret.Class + " *" { // "instancename"
// ret.ctype = ret.Class
// }
return ret
}
@ -141,6 +158,9 @@ func _goType(ct string) string {
ct = strings.Title(ct)
ct = strings.ReplaceAll(ct," ","")
ct = strings.ReplaceAll(ct,"Struct","")
if len(ct) > 0 && ct[0] == '*' && isGoInterface(ct[1:]) {
return ct[1:]
}
return ct
}
@ -208,13 +228,26 @@ func (t *Type) GoInterfaceDecl() string {
gt = gt[1:] // dereference wrapped types
}
super := Super(gt)
if goInterfaces == nil {
goInterfaces = make(map[string]bool)
}
if super == "" {
super = "ptr unsafe.Pointer"
goInterfaces[gt] = true
return fmt.Sprintf(`
//%s (%s)
type %s interface {
Ptr() unsafe.Pointer
}
`,t.Node.Ctype(),t.BaseType().GoType(),gt)
}
if isGoInterface(super) {
super = "Id"
}
return fmt.Sprintf(`
//%s (%s)
type %s struct { %s }
`,t.Node.Ctype(),t.BaseType().GoType(),gt,super)
func (o *%s) Ptr() unsafe.Pointer { return o.ptr }
`,t.Node.Ctype(),t.BaseType().GoType(),gt,super,gt)
}
func (t *Type) IsFunction() bool {
@ -242,12 +275,15 @@ func (t *Type) CToGo(cval string) string { // cast C value to CGo
func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
var ret strings.Builder
rt := rtype.CType()
wrap := func(gt string) bool {
return gt != "" && gt[0] == '*' && wrapped[gt[1:]]
}
if rt != "void" {
if wrap(rtype.GoType()) {
ret.WriteString(" ret := &" + rtype.GoType()[1:] + "{}\n")
rtgt := rtype.GoType()
if shouldWrap(rtgt) || isGoInterface(rtgt) {
if isGoInterface(rtgt) {
rtgt = "Id"
} else {
rtgt = rtgt[1:]
}
ret.WriteString(" ret := &" + rtgt + "{}\n")
ret.WriteString(" ret.ptr = unsafe.Pointer(")
} else {
ret.WriteString(" return (" + rtype.GoType() + ")(")
@ -261,8 +297,8 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
for i := 0; i < len(pnames); i++ {
pn,pt := pnames[i],ptypes[i]
p := pn
if wrap(pt.GoType()) {
p = pn + ".ptr"
if shouldWrap(pt.GoType()) || isGoInterface(pt.GoType()) {
p = pn + ".Ptr()"
} else {
if pt.Node.IsPointer() {
p = "unsafe.Pointer(" + pn + ")"
@ -275,7 +311,7 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
ret.WriteString(strings.Join(parms,", "))
ret.WriteString(")")
if rt != "void" {
if wrap(rtype.GoType()) {
if shouldWrap(rtype.GoType()) || isGoInterface(rtype.GoType()) {
ret.WriteString(`)
return ret
`)

View File

@ -35,6 +35,10 @@ func NewWrapper(debug bool) *Wrapper {
ret.cCode.WriteString(`/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation
`)
ret.goTypes.WriteString(`
type Id struct { ptr unsafe.Pointer }
func (o *Id) Ptr() unsafe.Pointer { return o.ptr }
`)
return ret
}
@ -331,12 +335,12 @@ func (w *Wrapper) processType(tp *types.Type) {
if bt.IsFunction() {
return
}
w.goTypes.WriteString(bt.GoTypeDecl())
super := types.Super(gt)
if super != "" {
types.Wrap(super)
w.processType(types.NewTypeFromString(super,""))
}
w.goTypes.WriteString(bt.GoTypeDecl())
}
func (w *Wrapper) CharHelpers() {