Complete conversion to pointer wrapped types. Update tests, fix

parameter handling for functions.
This commit is contained in:
Greg 2019-06-13 16:47:36 -04:00
parent ac9eecafd8
commit 79bb282188
12 changed files with 268 additions and 87 deletions

2
.gitignore vendored
View File

@ -13,4 +13,6 @@ examples/memory/memory
examples/memory/ns examples/memory/ns
examples/gc/gc examples/gc/gc
examples/gc/ns examples/gc/ns
examples/functions/functions
examples/functions/ns
ns-old ns-old

View File

@ -22,10 +22,6 @@ func pb2() {
func didFinishLaunching(n *ns.NSNotification) { func didFinishLaunching(n *ns.NSNotification) {
fmt.Println("Go: did finish launching") fmt.Println("Go: did finish launching")
fmt.Printf("Notification n = %p\n",n)
fmt.Printf("Notification n.Ptr() = %p\n",n.Ptr())
fmt.Printf("Notification n.Name() = %p\n",n.Name())
fmt.Printf("Notification n.Name().Ptr() = %p\n",n.Name().Ptr())
fmt.Printf("Notification: %s\n", n.Name().UTF8String()) fmt.Printf("Notification: %s\n", n.Name().UTF8String())
//Set up an NSWindow //Set up an NSWindow
win = ns.NSWindowAlloc().InitWithContentRectStyleMask( win = ns.NSWindowAlloc().InitWithContentRectStyleMask(

View File

@ -8,7 +8,7 @@ import (
"git.wow.st/gmp/nswrap/examples/bluetooth/ns" "git.wow.st/gmp/nswrap/examples/bluetooth/ns"
) )
func updateState(c ns.CBCentralManager) { func updateState(c *ns.CBCentralManager) {
fmt.Printf("Go: did update state\n") fmt.Printf("Go: did update state\n")
switch cm.CBManager.State() { switch cm.CBManager.State() {
case ns.CBManagerStateUnknown: case ns.CBManagerStateUnknown:
@ -23,11 +23,11 @@ func updateState(c ns.CBCentralManager) {
fmt.Printf(" powered off\n") fmt.Printf(" powered off\n")
case ns.CBManagerStatePoweredOn: case ns.CBManagerStatePoweredOn:
fmt.Printf(" powered on\n") fmt.Printf(" powered on\n")
cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid), ns.NSDictionary{}) cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid), nil)
} }
} }
func discoverPeripheral(c ns.CBCentralManager, p ns.CBPeripheral, d ns.NSDictionary, rssi ns.NSNumber) { func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
fmt.Printf("Did discover peripheral\n") fmt.Printf("Did discover peripheral\n")
c.StopScan() c.StopScan()
if peripheral.Ptr() != nil { if peripheral.Ptr() != nil {
@ -35,26 +35,26 @@ func discoverPeripheral(c ns.CBCentralManager, p ns.CBPeripheral, d ns.NSDiction
} }
peripheral = p peripheral = p
peripheral.Retain() peripheral.Retain()
c.ConnectPeripheral(peripheral, ns.NSDictionary{}) c.ConnectPeripheral(peripheral, nil)
} }
func connectPeripheral(c ns.CBCentralManager, p ns.CBPeripheral) { func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
fmt.Printf("Did connect peripheral\n") fmt.Printf("Did connect peripheral\n")
p.SetDelegate(cd) p.SetDelegate(cd)
p.DiscoverServices(ns.NSArray{}) p.DiscoverServices(nil)
} }
func discoverServices(p ns.CBPeripheral, e ns.NSError) { func discoverServices(p *ns.CBPeripheral, e *ns.NSError) {
fmt.Printf("Did discover services\n") fmt.Printf("Did discover services\n")
p.Services().ObjectEnumerator().ForIn(func(o ns.Id) bool { p.Services().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
serv := o.CBService() serv := o.CBService()
switch { switch {
case serv.UUID().IsEqualTo(hrm_uuid): case serv.UUID().IsEqualTo(hrm_uuid):
fmt.Printf("--heart rate monitor service\n") fmt.Printf("--heart rate monitor service\n")
p.DiscoverCharacteristics(ns.NSArray{}, serv) p.DiscoverCharacteristics(nil, serv)
case serv.UUID().IsEqualTo(ns.CBUUIDWithGoString("180A")): case serv.UUID().IsEqualTo(ns.CBUUIDWithGoString("180A")):
fmt.Printf("--device information service\n") fmt.Printf("--device information service\n")
p.DiscoverCharacteristics(ns.NSArray{}, serv) p.DiscoverCharacteristics(nil, serv)
default: default:
fmt.Printf("--unknown service\n") fmt.Printf("--unknown service\n")
} }
@ -62,7 +62,7 @@ func discoverServices(p ns.CBPeripheral, e ns.NSError) {
}) })
} }
func hr(d ns.NSData) int { func hr(d *ns.NSData) int {
if l := int(d.Length()); l < 4 { if l := int(d.Length()); l < 4 {
return 0 return 0
} }
@ -75,11 +75,11 @@ func hr(d ns.NSData) int {
} }
} }
func discoverCharacteristics(p ns.CBPeripheral, s ns.CBService, e ns.NSError) { func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) {
fmt.Printf("Did discover characteristics\n") fmt.Printf("Did discover characteristics\n")
fmt.Printf("----%s\n", s.UUID().UUIDString().UTF8String()) fmt.Printf("----%s\n", s.UUID().UUIDString().UTF8String())
if s.UUID().IsEqualTo(hrm_uuid) { if s.UUID().IsEqualTo(hrm_uuid) {
s.Characteristics().ObjectEnumerator().ForIn(func(o ns.Id) bool { s.Characteristics().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
chr := o.CBCharacteristic() chr := o.CBCharacteristic()
fmt.Printf("------%s\n", chr.UUID().UUIDString().UTF8String()) fmt.Printf("------%s\n", chr.UUID().UUIDString().UTF8String())
if chr.UUID().IsEqualTo(hrv_uuid) { if chr.UUID().IsEqualTo(hrv_uuid) {
@ -92,7 +92,7 @@ func discoverCharacteristics(p ns.CBPeripheral, s ns.CBService, e ns.NSError) {
} }
} }
func updateValue(p ns.CBPeripheral, chr ns.CBCharacteristic, e ns.NSError) { func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
if chr.UUID().IsEqualTo(hrv_uuid) { if chr.UUID().IsEqualTo(hrv_uuid) {
v := chr.Value() v := chr.Value()
fmt.Printf("Heart rate: %d\n", hr(v)) fmt.Printf("Heart rate: %d\n", hr(v))
@ -100,11 +100,11 @@ func updateValue(p ns.CBPeripheral, chr ns.CBCharacteristic, e ns.NSError) {
} }
var ( var (
hrm_uuid ns.CBUUID hrm_uuid *ns.CBUUID
hrv_uuid ns.CBUUID hrv_uuid *ns.CBUUID
cd ns.CBDelegate cd *ns.CBDelegate
cm ns.CBCentralManager cm *ns.CBCentralManager
peripheral ns.CBPeripheral peripheral *ns.CBPeripheral
) )
func main() { func main() {

View File

@ -38,4 +38,4 @@ delegates:
- peripheralDidUpdateValueForCharacteristic - peripheralDidUpdateValueForCharacteristic
pragma: [ clang diagnostic ignored "-Wformat-security" ] pragma: [ clang diagnostic ignored "-Wformat-security" ]
gogc: true #gogc: true

View File

@ -8,6 +8,11 @@ import (
"git.wow.st/gmp/nswrap/examples/foundation/ns" "git.wow.st/gmp/nswrap/examples/foundation/ns"
) )
var (
gs1 *ns.NSString
gs2 *ns.NSString
)
func main() { func main() {
fmt.Printf("Creating some strings:\n") fmt.Printf("Creating some strings:\n")
n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there")) n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there"))
@ -64,6 +69,19 @@ func main() {
} }
return true return true
}) })
fmt.Printf("\nNSArrayWithObjects() (length 1)\n")
a2 = ns.NSArrayWithObjects(n1)
a2.ObjectEnumerator().ForIn(func(o *ns.Id) bool {
switch {
case o.IsKindOfClass(ns.NSStringClass()):
fmt.Println(o.NSString().UTF8String())
return true // continue enumeration
default:
fmt.Println("Unknown class")
return false // terminate enumeration
}
})
fmt.Printf("\nNSArrayWithObjects()\n") fmt.Printf("\nNSArrayWithObjects()\n")
a2 = ns.NSArrayWithObjects(n1, n2, n3, s1) a2 = ns.NSArrayWithObjects(n1, n2, n3, s1)
fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n") fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n")
@ -101,4 +119,14 @@ func main() {
fmt.Printf("\nNSStringWithFormat()\n") fmt.Printf("\nNSStringWithFormat()\n")
str := ns.NSStringWithFormat(nst("(%@) (%@)\n(%@)\n"), n2, n3, s1) str := ns.NSStringWithFormat(nst("(%@) (%@)\n(%@)\n"), n2, n3, s1)
fmt.Printf("%s\n", str) fmt.Printf("%s\n", str)
fmt.Printf("\nGlobal strings\n")
gs1 = ns.NSStringWithGoString("global string 1")
gs2 = ns.NSStringWithGoString("global string 2")
fmt.Printf("\nArrayWithObjects\n")
a2 = ns.NSArrayWithObjects(gs1, gs2)
a2.ObjectEnumerator().ForIn(func(o *ns.Id) bool {
fmt.Printf("--%s\n",o.NSString())
return true
})
} }

View File

@ -0,0 +1,26 @@
package main
import (
"fmt"
"unsafe"
"git.wow.st/gmp/nswrap/examples/functions/ns"
)
func main() {
var s ns.Stat
ns.Puts(ns.CharWithGoString("Hi there"))
ret := ns.Fstat(3,&s)
fmt.Printf("Fstat: %d\n",ret)
fmt.Printf("Opening file\n")
f := ns.Fopen(ns.CharWithGoString("nswrap.yaml"),ns.CharWithGoString("r"))
ret = ns.Fstat(3,&s)
fmt.Printf("Fstat: %d\n",ret)
chr := make([]byte,4096)
i := ns.Fread(unsafe.Pointer(&chr[0]), 1, 4096, f)
if i < 4096 {
chr = chr[:i]
}
fmt.Printf("file contents:\n%s\n",string(chr))
}

View File

@ -0,0 +1,17 @@
inputfiles:
- /usr/include/stdio.h
- /usr/include/stdlib.h
- /usr/include/sys/stat.h
sysimports:
- stdio.h
- stdlib.h
- sys/stat.h
functions:
- sranddev
- cgetclose
- cgetset
- devname
- puts
- fstat
- fopen
- fread

View File

@ -2,6 +2,7 @@ package types
import ( import (
"fmt" "fmt"
"os"
"regexp" "regexp"
"strings" "strings"
) )
@ -12,6 +13,7 @@ var super map[string]string
//wrapped is a map recording whether a given GoType is to be "wrapped" in a //wrapped is a map recording whether a given GoType is to be "wrapped" in a
//go struct. //go struct.
var wrapped map[string]bool var wrapped map[string]bool
var tdptr map[string]bool
func ShouldWrap(gt string) bool { func ShouldWrap(gt string) bool {
return wrapped[gt] return wrapped[gt]
@ -21,6 +23,10 @@ func PtrShouldWrap(gt string) bool {
return gt != "" && gt[0] == '*' && wrapped[gt[1:]] return gt != "" && gt[0] == '*' && wrapped[gt[1:]]
} }
func TypedefShouldWrap(gt string) bool {
return tdptr[gt]
}
//goInterfaces records the names of top level Go interfaces. //goInterfaces records the names of top level Go interfaces.
var goInterfaces map[string]bool var goInterfaces map[string]bool
@ -52,6 +58,7 @@ var (
func init() { func init() {
super = make(map[string]string) super = make(map[string]string)
wrapped = make(map[string]bool) wrapped = make(map[string]bool)
tdptr = make(map[string]bool)
goInterfaces = make(map[string]bool) goInterfaces = make(map[string]bool)
TypeParameters = make(map[string]map[string]string) TypeParameters = make(map[string]map[string]string)
typedefs = make(map[string]*Type) typedefs = make(map[string]*Type)
@ -164,9 +171,6 @@ func (t *Type) BaseType() *Type {
if t == nil { if t == nil {
return nil return nil
} }
// if td := t.Typedef(); td != nil {
// return td.BaseType()
// }
ret := NewType( ret := NewType(
t.Node.BaseType(), t.Node.BaseType(),
t.Class, t.Class,
@ -201,14 +205,12 @@ func _goType(ct string) string {
ct = strings.TrimPrefix(ct, "Struct") ct = strings.TrimPrefix(ct, "Struct")
ct = swapstars(ct) ct = swapstars(ct)
if len(ct) > 0 && ct[0] == '*' && IsGoInterface(ct[1:]) { if len(ct) > 0 && ct[0] == '*' && IsGoInterface(ct[1:]) {
//return ct[1:] return ct
return ct // ??
} }
if ct == "Id" { if ct == "Id" {
ct = "*Id" ct = "*Id"
} }
//if len(ct) > 1 && ShouldWrap(ct[1:]) {
if ShouldWrap(ct) { if ShouldWrap(ct) {
return ct return ct
} }
@ -245,13 +247,32 @@ func (t *Type) _CType(attrib bool) string {
} }
func (t *Type) GoTypeDecl() string { func (t *Type) GoTypeDecl() string {
if wrapped[t.GoType()] { gt := t.GoType()
if wrapped[gt] {
return t.GoInterfaceDecl() return t.GoInterfaceDecl()
} }
if t.Node.IsId() { if t.Node.IsId() {
return "" return ""
} }
gt := t.GoType() if td := t.Typedef(); td != nil {
tdgt := td.GoType()
if ShouldWrap(tdgt) || PtrShouldWrap(tdgt) { // type alias
if PtrIsGoInterface(tdgt) {
tdgt = "*Id"
}
if IsGoInterface(tdgt) {
tdgt = "Id"
}
Wrap(gt)
tdptr[gt] = true
return fmt.Sprintf(`
type %s = %s
`, gt, tdgt)
}
return fmt.Sprintf(`
type %s %s
`, gt, td.CGoType())
}
if Debug { if Debug {
fmt.Printf(" writing GoTypeDecl for %s\n",gt) fmt.Printf(" writing GoTypeDecl for %s\n",gt)
} }
@ -376,20 +397,35 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu
//fmt.Printf(" PtrIsGoInterface(%s) = true\n",rtgt) //fmt.Printf(" PtrIsGoInterface(%s) = true\n",rtgt)
rtgt = "*Id" rtgt = "*Id"
} }
sw := PtrShouldWrap(rtgt) || rtgt == "*Id" sw := PtrShouldWrap(rtgt) || rtgt == "*Id" || TypedefShouldWrap(rtgt)
isptr := rtype.IsPointer()
if rt != "void" { if rt != "void" {
if sw { switch {
case PtrShouldWrap(rtgt), rtgt == "*Id":
isptr = true
if PtrIsGoInterface(rtgt) {
rtgt = "*Id"
}
ret.WriteString(fmt.Sprintf( ret.WriteString(fmt.Sprintf(
`ret := &%s{} `ret := &%s{}
ret.ptr = `, rtgt[1:])) ret.ptr = unsafe.Pointer(`, rtgt[1:]))
} else { case TypedefShouldWrap(rtgt):
isptr = true
rtgt := rtype.Typedef().GoType()
if PtrIsGoInterface(rtgt) {
rtgt = "*Id"
}
ret.WriteString(fmt.Sprintf(
`ret := &%s{}
ret.ptr = unsafe.Pointer(`, rtgt[1:]))
default:
if rtgt == "BOOL" { if rtgt == "BOOL" {
ret.WriteString("ret := (") ret.WriteString("ret := (")
rtgt = "bool" rtgt = "bool"
} else { } else {
ret.WriteString("ret := (" + rtgt + ")(") ret.WriteString("ret := (" + rtgt + ")(")
} }
if rtype.IsPointer() { if isptr {
ret.WriteString("unsafe.Pointer(") ret.WriteString("unsafe.Pointer(")
} }
} }
@ -398,20 +434,25 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu
parms := []string{} parms := []string{}
for i := 0; i < len(pnames); i++ { for i := 0; i < len(pnames); i++ {
pn, pt := pnames[i], ptypes[i] pn, pt := pnames[i], ptypes[i]
ptgt := pt.GoType()
p := pn p := pn
if (PtrShouldWrap(pt.GoType()) || PtrIsGoInterface(pt.GoType())) && !pt.Variadic { switch {
case (PtrShouldWrap(ptgt) || PtrIsGoInterface(ptgt)) && !pt.Variadic:
p = pn + ".Ptr()" p = pn + ".Ptr()"
} else { case TypedefShouldWrap(ptgt) && !pt.Variadic && fun:
switch { p = "(" + pt.CGoType() + ")(" + pn + ".Ptr())"
case snames[i] != "": case TypedefShouldWrap(ptgt) && !pt.Variadic && !fun:
p = "unsafe.Pointer(&" + snames[i] + "[0])" p = pn + ".Ptr()"
case pt.Variadic: case snames[i] != "":
p = "unsafe.Pointer(&" + p + ")" p = "unsafe.Pointer(&" + snames[i] + "[0])"
case pt.IsPointer() && !fun: case pt.Variadic:
p = "unsafe.Pointer(" + pn + ")" p = "unsafe.Pointer(&" + p + ")"
default: case pt.IsPointer() && !fun:
p = "(" + pt.CGoType() + ")(" + pn + ")" p = "unsafe.Pointer(" + pn + ")"
} case pt.IsPointer() && fun && pt.BaseType().CType() == "void":
p = pn
default:
p = "(" + pt.CGoType() + ")(" + pn + ")"
} }
parms = append(parms, p) parms = append(parms, p)
} }
@ -419,9 +460,9 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu
ret.WriteString(")") ret.WriteString(")")
if rt != "void" && !sw { if rt != "void" && !sw {
ret.WriteString(")") ret.WriteString(")")
if rtype.IsPointer() { }
ret.WriteString(")") if isptr {
} ret.WriteString(")")
} }
if rt == "BOOL" { if rt == "BOOL" {
ret.WriteString(" != 0") ret.WriteString(" != 0")
@ -430,7 +471,12 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu
if sname == "" { if sname == "" {
continue continue
} }
ptgt := (ptypes[i].GoType())[2:] ptgt := ptypes[i].GoType()
if len(ptgt) < 2 {
fmt.Printf("Error in function translation -- argument %s to %s should be pointer to pointer\n",pnames[i],name)
os.Exit(-1)
}
ptgt = ptgt[2:]
if IsGoInterface(ptgt) { if IsGoInterface(ptgt) {
ptgt = "Id" ptgt = "Id"
} }
@ -450,7 +496,7 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu
if rt != "void" { if rt != "void" {
if fin { if fin {
ret.WriteString(fmt.Sprintf(` ret.WriteString(fmt.Sprintf(`
runtime.SetFinalizer(ret, func(o *%s) { runtime.SetFinalizer(ret, func(o %s) {
o.Release() o.Release()
})`,rtgt)) })`,rtgt))
} }

View File

@ -51,6 +51,12 @@ func TestType(t *testing.T) {
chk_newtype() chk_newtype()
tint := tp tint := tp
str = "id"
n = &Node{"TypeName", "", []*Node{
&Node{"TypedefName", "id", []*Node{}}}}
chk_newtype()
//nsid := tp
str = "NSObject" str = "NSObject"
n = &Node{"TypeName", "", []*Node{ n = &Node{"TypeName", "", []*Node{
&Node{"TypedefName", "NSObject", []*Node{}}}} &Node{"TypedefName", "NSObject", []*Node{}}}}
@ -63,6 +69,33 @@ func TestType(t *testing.T) {
chk_newtype() chk_newtype()
nst := tp nst := tp
str = "NSString**"
n = &Node{"TypeName", "", []*Node{
&Node{"TypedefName", "NSString", []*Node{}},
&Node{"Pointer", "*", []*Node{}},
&Node{"Pointer", "*", []*Node{}}}}
chk_newtype()
chk(tp.IsPointer(), true)
chk(tp.Typedef(), nil)
nstpp := tp
str = "NSObject**"
n = &Node{"TypeName", "", []*Node{
&Node{"TypedefName", "NSObject", []*Node{}},
&Node{"Pointer", "*", []*Node{}},
&Node{"Pointer", "*", []*Node{}}}}
chk_newtype()
chk(tp.IsPointer(), true)
nsopp := tp
str = "NSObject*"
n = &Node{"TypeName", "", []*Node{
&Node{"TypedefName", "NSObject", []*Node{}},
&Node{"Pointer", "*", []*Node{}}}}
chk_newtype()
chk(tp.IsPointer(), true)
nsop := tp
str = "NSString*" str = "NSString*"
n = &Node{"TypeName", "", []*Node{ n = &Node{"TypeName", "", []*Node{
&Node{"TypedefName", "NSString", []*Node{}}, &Node{"TypedefName", "NSString", []*Node{}},
@ -70,14 +103,14 @@ func TestType(t *testing.T) {
chk_newtype() chk_newtype()
chk(tp.IsPointer(), true) chk(tp.IsPointer(), true)
chk(tp.Typedef(), nil) chk(tp.Typedef(), nil)
tpNSString := tp nstp := tp
str = "myTypedef" str = "myTypedef"
AddTypedef("myTypedef", tp) AddTypedef("myTypedef", tp)
n = &Node{"TypeName", "", []*Node{ n = &Node{"TypeName", "", []*Node{
&Node{"TypedefName", "myTypedef", []*Node{}}}} &Node{"TypedefName", "myTypedef", []*Node{}}}}
chk_newtype() chk_newtype()
chk(tp.Typedef(), tpNSString) chk(tp.Typedef(), nstp)
str = "const NSArray <ObjectType * _Nonnull> *" str = "const NSArray <ObjectType * _Nonnull> *"
n = &Node{"TypeName", "", []*Node{ n = &Node{"TypeName", "", []*Node{
@ -146,10 +179,6 @@ func TestType(t *testing.T) {
chk(tp.GoTypeDecl(), ` chk(tp.GoTypeDecl(), `
type MyTypedef **C.NSObject type MyTypedef **C.NSObject
`)
chk(tp2.GoTypeDecl(), "")
chk(nst.GoTypeDecl(), `
type NSString C.NSString
`) `)
str = "void" str = "void"
n = &Node{"TypeName", "", []*Node{ n = &Node{"TypeName", "", []*Node{
@ -174,7 +203,7 @@ type NSString C.NSString
str = "NSObject*" str = "NSObject*"
n, _ = Parse(str) n, _ = Parse(str)
chk_newtype() chk_newtype()
chk(tp.GoType(), "NSObject") chk(tp.GoType(), "*NSObject")
Wrap("NSString") Wrap("NSString")
chk(nso.GoTypeDecl(), ` chk(nso.GoTypeDecl(), `
@ -186,9 +215,9 @@ type NSObject interface {
chk(nst.GoTypeDecl(), ` chk(nst.GoTypeDecl(), `
type NSString struct { Id } type NSString struct { Id }
func (o NSString) Ptr() unsafe.Pointer { return o.ptr } func (o *NSString) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr }
func (o Id) NSString() NSString { func (o *Id) NSString() *NSString {
ret := NSString{} ret := &NSString{}
ret.ptr = o.ptr ret.ptr = o.ptr
return ret return ret
} }
@ -242,12 +271,13 @@ func (o Id) NSString() NSString {
str = "GoToC" str = "GoToC"
var rtype *Type var rtype *Type
ptypes := []*Type{nst, nso, tint, voidpp} ptypes := []*Type{nsop, nstp, tint, voidpp}
pnames := []string{"p1", "p2", "p3", "p4"} pnames := []string{"p1", "p2", "p3", "p4"}
snames := []string{"", "", "", ""} snames := []string{"", "", "", ""}
chk_gotoc := func(expected string) { chk_gotoc := func(expected string) {
chk(GoToC("myFun", pnames, snames, rtype, ptypes, false), expected) fmt.Printf("chk_gotoc\n")
chk(GoToC("myFun", pnames, snames, rtype, ptypes, false, false), expected)
} }
chk_gotoc("") chk_gotoc("")
@ -265,61 +295,75 @@ func (o Id) NSString() NSString {
`ret := (*unsafe.Pointer)(unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))) `ret := (*unsafe.Pointer)(unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))))
return ret`) return ret`)
rtype = nst rtype = nstp
chk_gotoc( chk_gotoc(
`ret := NSString{} `ret := &NSString{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))
return ret`) return ret`)
rtype = nso rtype = nsop
chk_gotoc( chk_gotoc(
`ret := Id{} `ret := &Id{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))
return ret`) return ret`)
ptypes[1].Variadic = true ptypes[1].Variadic = true
ptypes[0].Variadic = false
chk_gotoc( chk_gotoc(
`ret := Id{} `ret := &Id{}
ret.ptr = C.myFun(p1.Ptr(), unsafe.Pointer(&p2), (C.int)(p3), unsafe.Pointer(p4)) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), unsafe.Pointer(&p2), (C.int)(p3), unsafe.Pointer(p4)))
return ret`) return ret`)
ptypes[1].Variadic = false
ptypes[1].Variadic = false
snames[1] = "p2p" snames[1] = "p2p"
ptypes[1] = nsopp
chk_gotoc( chk_gotoc(
`ret := Id{} `ret := &Id{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), unsafe.Pointer(&p2p[0]), (C.int)(p3), unsafe.Pointer(p4)))
(*p2) = (*p2)[:cap(*p2)] (*p2) = (*p2)[:cap(*p2)]
for i := 0; i < len(*p2); i++ { for i := 0; i < len(*p2); i++ {
if p2p[i] == nil { if p2p[i] == nil {
(*p2) = (*p2)[:i] (*p2) = (*p2)[:i]
break break
} }
if (*p2)[i] == nil {
(*p2)[i] = &Id{}
}
(*p2)[i].ptr = p2p[i] (*p2)[i].ptr = p2p[i]
} }
return ret`) return ret`)
snames[1] = "" snames[1] = ""
snames[2] = "p3p" snames[2] = "p3p"
ptypes[1] = nsop
ptypes[2] = nstpp
chk_gotoc( chk_gotoc(
`ret := Id{} `ret := &Id{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), unsafe.Pointer(p4)) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), unsafe.Pointer(p4)))
(*p3) = (*p3)[:cap(*p3)] (*p3) = (*p3)[:cap(*p3)]
for i := 0; i < len(*p3); i++ { for i := 0; i < len(*p3); i++ {
if p3p[i] == nil { if p3p[i] == nil {
(*p3) = (*p3)[:i] (*p3) = (*p3)[:i]
break break
} }
if (*p3)[i] == nil {
(*p3)[i] = &NSString{}
}
(*p3)[i].ptr = p3p[i] (*p3)[i].ptr = p3p[i]
} }
return ret`) return ret`)
chk(GoToC("myFun", pnames, snames, rtype, ptypes, true),
`ret := Id{} chk(GoToC("myFun", pnames, snames, rtype, ptypes, true, false),
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), (**C.void)(p4)) `ret := &Id{}
ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), p4))
(*p3) = (*p3)[:cap(*p3)] (*p3) = (*p3)[:cap(*p3)]
for i := 0; i < len(*p3); i++ { for i := 0; i < len(*p3); i++ {
if p3p[i] == nil { if p3p[i] == nil {
(*p3) = (*p3)[:i] (*p3) = (*p3)[:i]
break break
} }
if (*p3)[i] == nil {
(*p3)[i] = &NSString{}
}
(*p3)[i].ptr = p3p[i] (*p3)[i].ptr = p3p[i]
} }
return ret`) return ret`)

View File

@ -236,6 +236,7 @@ func TypeQualifier(s string, n *Node) (string, *Node) {
Word("const"), Word("const"),
Word("restrict"), Word("restrict"),
Word("volatile"), Word("volatile"),
Word("__restrict"),
))(s, n) ))(s, n)
} }

View File

@ -209,6 +209,24 @@ func TestParse(t *testing.T) {
-<TypeSpecifier> 'int' -<TypeSpecifier> 'int'
-<Pointer> '*' -<Pointer> '*'
-<Function> '' -<Function> ''
`)
runParseTest(`int *(char*)`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'char'
---<Pointer> '*'
`)
runParseTest(`RANGE *(char*)`,
`<TypeName> ''
-<TypedefName> 'RANGE'
-<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'char'
---<Pointer> '*'
`) `)
runParseTest(`int (*)(void)`, runParseTest(`int (*)(void)`,
`<TypeName> '' `<TypeName> ''

View File

@ -319,11 +319,14 @@ func (w *Wrapper) gpntp(m *Method) ([]string, []string, []*types.Type, string) {
ns = append(ns, "o") ns = append(ns, "o")
tps = append(tps, types.NewTypeFromString(m.Class+"*", "")) tps = append(tps, types.NewTypeFromString(m.Class+"*", ""))
} }
for _, p := range m.Parameters { for i, p := range m.Parameters {
gname := p.Vname gname := p.Vname
if goreserved[gname] { if goreserved[gname] {
gname = gname + "_" gname = gname + "_"
} }
if gname == "" {
gname = fmt.Sprintf("p%d",i)
}
ns = append(ns, gname) ns = append(ns, gname)
tps = append(tps, p.Type) tps = append(tps, p.Type)
} }
@ -1688,14 +1691,14 @@ func (d %s) %sCallback(f func(%s)%s) {
} else { } else {
gt2 = gtypes[i][j-1] gt2 = gtypes[i][j-1]
} }
if types.IsGoInterface(gt2) || types.ShouldWrap(gt2) { if types.PtrIsGoInterface(gt2) {
gt2 = "*Id" gt2 = "*Id"
} }
if gt2 == "*Id" { if gt2 == "*Id" || types.PtrShouldWrap(gt2) {
garglist = append(garglist, fmt.Sprintf( garglist = append(garglist, fmt.Sprintf(
`a%d`, j)) `a%d`, j))
gargconv = append(gargconv, fmt.Sprintf( gargconv = append(gargconv, fmt.Sprintf(
` a%d := %s{}; a%d.ptr = %s`, j, gt2, j, vnames[i][j])) ` a%d := &%s{}; a%d.ptr = %s`, j, gt2[1:], j, vnames[i][j]))
} else { } else {
garglist = append(garglist, fmt.Sprintf( garglist = append(garglist, fmt.Sprintf(
`(%s)(%s)`, gt2, vnames[i][j])) `(%s)(%s)`, gt2, vnames[i][j]))