First draft that handles subclasses and improvements to delegate

implementation.
This commit is contained in:
Greg 2019-05-21 16:26:52 -04:00
parent 8de87cddb7
commit 4f6930002d
7 changed files with 298 additions and 87 deletions

View File

@ -27,7 +27,8 @@ type conf struct {
Classes []string
Functions []string
Enums []string
Delegates map[string][]string
Delegates map[string]map[string][]string
Subclasses map[string]map[string][]string
Frameworks []string
Imports []string
Sysimports []string
@ -204,6 +205,7 @@ func Start() (err error) {
w.SysImport(Config.Sysimports)
w.Pragma(Config.Pragma)
w.Delegate(Config.Delegates)
w.Subclass(Config.Subclasses)
if Config.Vaargs == 0 {
Config.Vaargs = 16
}
@ -214,6 +216,13 @@ func Start() (err error) {
switch x := n.(type) {
case *ast.ObjCInterfaceDecl:
w.AddInterface(x)
for _,ss := range Config.Subclasses {
for ps,_ := range ss {
if matches(x.Name,[]string{ps}) {
Config.Classes = append(Config.Classes,x.Name)
}
}
}
case *ast.ObjCCategoryDecl:
w.AddCategory(x)
case *ast.TypedefDecl:
@ -223,11 +232,13 @@ func Start() (err error) {
w.AddFunction(x)
}
case *ast.ObjCProtocolDecl:
for _,ps := range Config.Delegates {
if matches(x.Name,ps) {
for _,ds := range Config.Delegates {
for ps,_ := range ds {
if matches(x.Name,[]string{ps}) {
w.AddProtocol(x)
}
}
}
case *ast.EnumDecl:
w.AddEnum(x,Config.Enums)
}

View File

@ -7,15 +7,12 @@ import (
"gitlab.wow.st/gmp/nswrap/examples/app/ns"
)
var nst = ns.NSStringWithGoString
func didFinishLaunching(n *ns.NSNotification) {
fmt.Println("Go: did finish launching")
}
func shouldTerminate(s *ns.NSApplication) ns.NSApplicationTerminateReply {
fmt.Println("Go: should terminate")
return ns.NSTerminateNow
}
func shouldTerminateAfterLastWindowClosed(s *ns.NSApplication) ns.BOOL {
return 1
}
@ -26,8 +23,18 @@ func willTerminate(n *ns.NSNotification) {
func didBecomeActive(n *ns.NSNotification) {
fmt.Println("Go: did become active")
vc := win.ContentViewController()
if vc == nil {
fmt.Println("vc == nil")
} else {
fmt.Println("vc is not nil")
}
}
var (
win *ns.NSWindow
)
func app() {
//Lock OS thread because Cocoa uses thread-local storage
runtime.LockOSThread()
@ -37,24 +44,23 @@ func app() {
//Set up an AppDelegate
del := ns.AppDelegateAlloc()
del.ApplicationDidFinishLaunchingCallback(didFinishLaunching)
del.ApplicationShouldTerminateCallback(shouldTerminate)
del.ApplicationShouldTerminateAfterLastWindowClosedCallback(shouldTerminateAfterLastWindowClosed)
del.ApplicationWillTerminateCallback(willTerminate)
del.ApplicationDidBecomeActiveCallback(didBecomeActive)
a.SetDelegate(del)
//Set up an NSWindow
w := ns.NSWindowAlloc().InitWithContentRect(
win = ns.NSWindowAlloc().InitWithContentRect(
ns.NSMakeRect(200,200,600,600),
ns.NSWindowStyleMaskTitled | ns.NSWindowStyleMaskClosable,
ns.NSWindowStyleMaskTitled | ns.NSWindowStyleMaskClosable |
ns.NSWindowStyleMaskResizable,
ns.NSBackingStoreBuffered,
0,
nil,
)
nst := ns.NSStringWithGoString
w.SetTitle(nst("Hi World"))
w.MakeKeyAndOrderFront(w)
w.SetAlphaValue(0.85)
win.SetTitle(nst("Hi World"))
win.MakeKeyAndOrderFront(win)
win.SetAlphaValue(0.85)
//Build a basic menu
m1 := ns.NSMenuAlloc().InitWithTitle(nst("Main"))
@ -68,21 +74,15 @@ func app() {
m1.SetSubmenu(appMenu, appItem)
m1.SetSubmenu(fileMenu, fileItem)
s := ns.NSStringWithGoString("")
appMenu.AddItemWithTitle(nst("About"), nil, s)
appMenu.AddItemWithTitle(nst("Preferences"), nil, s)
appMenu.AddItemWithTitle(nst("About"), nil, nst(""))
appMenu.AddItemWithTitle(nst("Preferences"), nil, nst(""))
appMenu.AddItemWithTitle(nst("Quit"),ns.Selector("terminate:"), nst("q"))
a.SetMainMenu(m1)
fileMenu.AddItemWithTitle(nst("Open"), nil, s)
fileMenu.AddItemWithTitle(nst("New"), nil, s)
fileMenu.AddItemWithTitle(nst("Open"), nil, nst(""))
fileMenu.AddItemWithTitle(nst("New"), nil, nst(""))
a.SetMainMenu(m1)
//Add a random button that does nothing
b1 := ns.NSButtonWithTitle(nst("push"),s,nil)
b1.Id.NSView().SetFrame(ns.NSMakeRect(0,550,100,50))
w.ContentView().AddSubview(&b1.NSView,ns.NSWindowAbove,nil)
//Run the app
a.Run()
}

View File

@ -4,31 +4,20 @@ inputfiles:
classes:
- NSAutoreleasePool
- NSArray
- NSMutableArray
- NSDictionary
- NSEnumerator
- NSSet
- NSDate
- NSTimeZone
- NSCalendar
- NSLocale
- NSCharacterSet
- NSString
- NSScanner
- NSFileManager
- NSApplication
- NSBundle
- NSApp
- NSMenu
- NSMenuItem
- NSWindow
- NSView
- NSScreen
- NSMenu
- NSMenuItem
- NSButton
- NSEvent
- NSResponder
- NSRunLoop
- NSNotification
- NSStackView
- NSLayoutConstraint
- NSDictionary
- NSArray
- NSColor
functions: [NSMake.*]
@ -41,7 +30,18 @@ enums:
- NSWindowOrderingMode
delegates:
AppDelegate: [NSApplicationDelegate]
AppDelegate:
NSApplicationDelegate:
- applicationWillTerminate
- applicationDidFinishLaunching
- applicationShouldTerminateAfterLastWindowClosed
- applicationDidBecomeActive
subclasses:
ViewController:
NSViewController:
- viewDidLoad
- viewDidDisappear
- loadView
frameworks: [ Foundation, AppKit, CoreGraphics ]
pragma: [ clang diagnostic ignored "-Wformat-security" ]

View File

@ -27,6 +27,14 @@ functions: [ NSMakeRange, dispatch_queue_create ]
enums: [ CB.* ]
frameworks: [ Foundation, CoreBluetooth ]
delegates:
BleDelegate: [ CBCentralManagerDelegate, CBPeripheralDelegate ]
BleDelegate:
CBCentralManagerDelegate:
- centralManagerDidUpdateState
- centralManagerDidDiscoverPeripheral
- centralManagerDidConnectPeripheral
CBPeripheralDelegate:
- peripheralDidDiscoverServices
- peripheralDidDiscoverCharacteristicsForService
- peripheralDidUpdateValueForCharacteristic
pragma: [ clang diagnostic ignored "-Wformat-security" ]

View File

@ -20,5 +20,7 @@ func main() {
fmt.Println(o.Hi2(np))
o2 := ns.ClassTwoAlloc().Init()
fmt.Println(o2.Hi1(ns1))
o3 := ns.ClassThreeAlloc().Init()
fmt.Println(o3.Hi2(np))
}

View File

@ -3,5 +3,9 @@ inputfiles: [ ClassOne/simple.h ]
classes:
- ClassOne
- ClassTwo
subclasses:
ClassThree:
ClassTwo:
- hi.*
imports: [ simple.h ]
frameworks: [ Foundation ]

View File

@ -22,11 +22,12 @@ type Wrapper struct {
Functions map[string]*Method
NamedEnums map[string]*Enum
AnonEnums []*Enum
Delegates map[string][]string
Delegates map[string]map[string][]string
Subclasses map[string]map[string][]string
Protocols map[string]*Protocol
cgoFlags strings.Builder // put cGo directives here
cImports strings.Builder // put c imports and sysimports here
cImports strings.Builder // put C imports and sysimports here
cCode strings.Builder // put cGo code here
goTypes strings.Builder // put Go type declarations here
goConst strings.Builder // put Go constants (from C enums) here
@ -87,10 +88,14 @@ func (w *Wrapper) Pragma(ss []string) {
}
}
func (w *Wrapper) Delegate(ds map[string][]string) {
func (w *Wrapper) Delegate(ds map[string]map[string][]string) {
w.Delegates = ds
}
func (w *Wrapper) Subclass(ds map[string]map[string][]string) {
w.Subclasses = ds
}
type Property struct {
Name, Attr string
Type *types.Type
@ -312,8 +317,8 @@ func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
if x := p.Polymorphic[m.Name]; x != 0 {
p.Polymorphic[m.Name] = x + 1
pname = pname + strings.Title(m.Parameters[1].Pname)
if m2 := p.Methods[m.Name]; m2 != nil {
pname2 := strings.Title(m.Name) + strings.Title(m2.Parameters[1].Pname)
if m2 := p.Methods[pname]; m2 != nil {
pname2 := pname + strings.Title(m2.Parameters[1].Pname)
p.Methods[pname2] = m2
delete(p.Methods,m.Name)
}
@ -380,7 +385,7 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl,rs []string) {
func (w *Wrapper) add(name string, ns []ast.Node) {
var i *Interface
var ok bool
goname := types.NewTypeFromString(name,name).GoType()
goname := strings.Title(types.NewTypeFromString(name,name).GoType())
types.Wrap(goname)
if i,ok = w.Interfaces[name]; !ok {
i = &Interface{
@ -418,7 +423,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
//fmt.Println(m.Type.Node.String())
m.Parameters, avail = w.GetParms(x,name)
if avail {
i.Methods[m.Name] = m
i.Methods[strings.Title(m.Name)] = m
}
case *ast.ObjCProtocol:
//fmt.Printf("ast.ObjCProtocol: %s\n",x.Name)
@ -462,7 +467,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
}
m2.Parameters = append(m2.Parameters,p2)
}
i.Methods[m.Name] = m2
i.Methods[strings.Title(m.Name)] = m2
}
}
supmethods(i,types.Super(s))
@ -875,8 +880,16 @@ const %s %s= C.%s
}
}
func (w *Wrapper) ProcessSubclass(sname string, ps map[string][]string) {
w._ProcessDelSub(sname,ps,true)
}
func (w *Wrapper) ProcessDelegate(dname string, ps map[string][]string) {
w._ProcessDelSub(dname,ps,false)
}
//NOTE: The delegate wrapper does not support variadic callback functions.
func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string,sub bool) {
//To create (per delegate):
//1. ObjC interface
//2. ObjC implementation
@ -884,10 +897,12 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
//4. Go type
//5. Go constructor
//6. Go dispatch database for callbacks
//7. Go superclass dispatch function
//To create (per method):
//1. ObjC function prototypes for go exports
//2. Go callback registration functions
//3. Go exported callback function wrappers
//4. Go wrapper functions for superclass methods
//organize output into string builders
var cprotos, ccode, gotypes, gocode, goexports strings.Builder
@ -895,14 +910,38 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
//set up array of methods for this delegate
methods := []*Method{}
gnames := []string{} // go names for methods
for _,pname := range ps {
pnames := make([]string,len(ps))
var supr string
i := 0
for pname,pats := range ps {
pnames[i] = pname
i++
var ms map[string]*Method
if sub {
interf := w.Interfaces[pname]
if interf == nil {
fmt.Printf("Failed to find interface %s for subclass %s\n",pname,dname)
os.Exit(-1)
}
//fmt.Printf(" subclass for %s\n",pname)
ms = interf.Methods
supr = interf.GoName
} else {
proto := w.Protocols[pname]
if proto == nil {
fmt.Printf("Failed to find protocol %s for delegate %s\n",pname,dname)
os.Exit(-1)
}
fmt.Printf(" proto %s\n",pname)
for gname,m := range proto.Methods {
//fmt.Printf(" proto %s\n",pname)
ms = proto.Methods
supr = "Id"
}
for gname,m := range ms {
//note:we may have capitalized the first character to make a goname,
//but m.Name is not disambiguated for polymorphics...
if !matches(string(m.Name[0])+gname[1:],pats) {
continue
}
if m.Type.IsFunction() || m.Type.IsFunctionPtr() || m.hasFunctionParam() {
continue
}
@ -912,8 +951,11 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
}
methprotos := make([]string,len(methods)) // objc method prototypes
smethprotos := make([]string,len(methods)) // super method prototypes
sfunprotos := make([]string,len(methods)) // super method prototypes
gname := strings.Title(dname) // go name for this Delegate
vnames := make([][]string,len(methods)) // objc variable names
vpnames := make([][]string,len(methods)) // objc parameter:variable names
gtypes := make([][]string,len(methods)) // go parameter types for each method
getypes := make([][]string,len(methods)) // parameter types for go export
grtypes := make([]string,len(methods)) // go retrun types for each method
@ -921,46 +963,68 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
crtypes := make([]string,len(methods)) // c return types for each method
//1. ObjC interface
fmt.Printf("Delegate %s <%s>: %d methods\n",dname,strings.Join(ps,", "),len(methods))
if sub {
fmt.Printf("Subclass ")
} else {
fmt.Printf("Delegate ")
}
fmt.Printf("%s <%s>: %d methods\n",dname,strings.Join(pnames,", "),len(methods))
for i,m := range methods {
w.processType(m.Type)
vnames[i] = make([]string,len(m.Parameters)+1)
vpnames[i] = make([]string,len(m.Parameters))
getypes[i] = make([]string,len(m.Parameters)+1)
vnames[i][0] = "self"
getypes[i][0] = "unsafe.Pointer"
gtypes[i] = make([]string,len(m.Parameters))
gtypes[i] = make([]string,len(m.Parameters)+1)
gtypes[i][0] = gname + "Supermethods"
//fmt.Printf("%s: %s\n",dname,m.Name)
var parms string
var cparms string
if len(m.Parameters) == 0 {
parms = ""
cparms = "void* self"
vpnames[i] = []string{m.Name}
} else {
pm := m.Parameters[0]
w.processType(pm.Type)
parms = fmt.Sprintf(":(%s)%s",pm.Type.Node.CType(),pm.Vname)
cparms = fmt.Sprintf("void* self, %s %s",pm.Type.Node.CType(),pm.Vname)
vnames[i][1] = pm.Vname
gtypes[i][0] = pm.Type.GoType()
vpnames[i][0] = pm.Pname + ":" + pm.Vname
gtypes[i][1] = pm.Type.GoType()
if pm.Type.IsPointer() {
getypes[i][1] = "unsafe.Pointer"
} else {
getypes[i][1] = gtypes[i][0]
getypes[i][1] = gtypes[i][1]
}
}
for j := 1; j < len(m.Parameters); j++ {
pm := m.Parameters[j]
w.processType(pm.Type)
parms = parms + fmt.Sprintf(" %s:(%s)%s",pm.Pname,pm.Type.Node.CType(),pm.Vname)
cparms = cparms + fmt.Sprintf(", %s %s",pm.Type.Node.CType(),pm.Vname)
vnames[i][j+1] = pm.Vname
gtypes[i][j] = pm.Type.GoType()
vpnames[i][j] = pm.Pname + ":" + pm.Vname
gtypes[i][j+1] = pm.Type.GoType()
var getp string
if pm.Type.IsPointer() {
getp = "unsafe.Pointer"
} else {
getp = gtypes[i][j]
getp = gtypes[i][j+1]
}
getypes[i][j+1] = getp
}
methprotos[i] = fmt.Sprintf(
`- (%s)%s%s;`,m.Type.Node.CType(),m.Name,parms)
ct := m.Type.Node.CType()
smethprotos[i] = fmt.Sprintf(
`- (%s)super_%s%s;`,ct,m.Name,parms)
if ct == "instancetype" {
ct = gname + "*"
}
sfunprotos[i] = fmt.Sprintf(
`%s %s_super_%s(%s);`,ct,dname,m.Name,cparms)
if x := m.Type.GoType(); x == "Void" {
grtypes[i] = ""
} else {
@ -984,16 +1048,38 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
cgtypes[i] = m.Type.CGoType()
}
}
var supcls string
var protos string
if sub {
supcls = pnames[0]
protos = ""
} else {
supcls = "NSObject"
protos = "<" + strings.Join(pnames,", ") + ">"
}
ccode.WriteString(fmt.Sprintf(`
@interface %s : NSObject <%s>
@interface %s : %s %s
{ }
%s
`,dname,supcls,protos,strings.Join(methprotos,"\n")))
if sub {
ccode.WriteString(strings.Join(smethprotos,"\n"))
}
ccode.WriteString(`
@end
`,dname,strings.Join(ps,", "),strings.Join(methprotos,"\n")))
`)
if sub {
ccode.WriteString(strings.Join(sfunprotos,"\n"))
}
//2. ObjC implementation
methdecls := make([]string,len(methods))
smethdecls := make([]string,len(methods))
sfundecls := make([]string,len(methods))
for i,mp := range methprotos {
mp := mp[:len(mp)-1]
smp := smethprotos[i][:len(smethprotos[i])-1]
sfp := sfunprotos[i][:len(sfunprotos[i])-1]
var ret string
if crtypes[i] != "void" {
ret = "return "
@ -1002,13 +1088,42 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
%s
{
%s%s(%s);
}`,mp[:len(mp)-1],ret,gname + gnames[i],strings.Join(vnames[i],", "))
}
`,mp,ret,gname + gnames[i],strings.Join(vnames[i],", "))
methdecls[i] = fmt.Sprintf(`
%s
{
%s%s(%s);
}
`,mp,ret,gname + gnames[i],strings.Join(vnames[i],", "))
if sub {
smethdecls[i] = fmt.Sprintf(`
%s
{
%s[super %s];
}
`,smp,ret,strings.Join(vpnames[i]," "))
sfundecls[i] = fmt.Sprintf(`
%s
{
%s[%s super_%s];
}
`,sfp,ret,gname,strings.Join(vpnames[i]," "))
}
}
ccode.WriteString(fmt.Sprintf(`
@implementation %s
%s
@end
`,dname,strings.Join(methdecls,"\n")))
if sub {
ccode.WriteString(strings.Join(smethdecls,"\n"))
}
ccode.WriteString(`
@end
`)
if sub {
ccode.WriteString(strings.Join(sfundecls,"\n"))
}
//3. ObjC constructor function
ccode.WriteString(fmt.Sprintf(`
@ -1019,11 +1134,12 @@ void*
`,dname,dname))
//4. Go type
gotypes.WriteString(fmt.Sprintf(`
type %s struct { Id }
type %s struct { %s }
func (o *%s) Ptr() unsafe.Pointer { return unsafe.Pointer(o) }
func (o *Id) %s() *%s { return (*%s)(unsafe.Pointer(o)) }
`,gname,gname,gname,gname,gname))
`,gname,supr,gname,gname,gname,gname))
//5. Go constructor
gocode.WriteString(fmt.Sprintf(`
@ -1034,17 +1150,32 @@ func %sAlloc() *%s {
//6. Go dispatch database for callbacks
dispitems := make([]string,len(gnames))
sdispitems := make([]string,len(gnames))
for i,n := range gnames {
if !sub {
gtypes[i] = gtypes[i][1:]
}
dispitems[i] = fmt.Sprintf(
` %s func(%s)%s`,n,strings.Join(gtypes[i],", "),grtypes[i])
if sub {
sdispitems[i] = fmt.Sprintf(
` %s func(%s)%s`,n,strings.Join(gtypes[i][1:],", "),grtypes[i])
}
}
gocode.WriteString(fmt.Sprintf(`
type %sDispatch struct {
%s
}
var %sLookup map[unsafe.Pointer]*%sDispatch =
map[unsafe.Pointer]*%sDispatch{}
var %sLookup map[unsafe.Pointer]%sDispatch =
map[unsafe.Pointer]%sDispatch{}
`,gname,strings.Join(dispitems,"\n"),gname,gname,gname))
if sub {
gocode.WriteString(fmt.Sprintf(`
type %sSupermethods struct {
%s
}
`,gname,strings.Join(sdispitems,"\n")))
}
//To create (per method):
cprotos.WriteString("\n\n")
for i,m := range methods {
@ -1057,19 +1188,24 @@ var %sLookup map[unsafe.Pointer]*%sDispatch =
gocode.WriteString(fmt.Sprintf(`
func (d *%s) %sCallback(f func(%s)%s) {
dispatch := %sLookup[d.Ptr()]
if dispatch == nil {
dispatch = &%sDispatch{}
%sLookup[d.Ptr()] = dispatch
}
dispatch.%s = f
%sLookup[d.Ptr()] = dispatch
}
`,gname,gnames[i],strings.Join(gtypes[i],", "),grtypes[i],gname,gname,gname,gnames[i]))
`,gname,gnames[i],strings.Join(gtypes[i],", "),grtypes[i],gname,gnames[i],gname))
//3. Go exported callback function wrappers
earglist := []string{"self unsafe.Pointer"}
earglist := []string{"o unsafe.Pointer"}
garglist := []string{}
if sub {
garglist = []string{"super"}
}
for j := 1; j < len(vnames[i]); j++ {
earglist = append(earglist,vnames[i][j] + " " + getypes[i][j])
gt2 := gtypes[i][j-1]
var gt2 string
if sub {
gt2 = gtypes[i][j]
} else {
gt2 = gtypes[i][j-1]
}
if types.IsGoInterface(gt2) {
gt2 = "*Id"
}
@ -1093,14 +1229,59 @@ func (d *%s) %sCallback(f func(%s)%s) {
}
retnparen = ")"
}
sdispentries := []string{}
for _,n := range gnames {
sdispentries = append(sdispentries,fmt.Sprintf(
` self.Super%s`,n))
}
sper := ""
if sub && len(gnames) > 0 {
sper = fmt.Sprintf(
`self := (*%s)(o)
super := %sSupermethods{
%s,
}
`,gname,gname,strings.Join(sdispentries,",\n"))
}
goexports.WriteString(fmt.Sprintf(`
//export %s%s
func %s%s(%s)%s {
%scb := %sLookup[self].%s
%scb := %sLookup[o].%s
if cb == nil { return%s }
%scb(%s)%s
%s%scb(%s)%s
}
`,gname,gnames[i],gname,gnames[i],strings.Join(earglist,", "),crtype,retdecl,gname,gnames[i],retname,retn,strings.Join(garglist,", "),retnparen))
`,gname,gnames[i],gname,gnames[i],strings.Join(earglist,", "),crtype,retdecl,gname,gnames[i],retname,sper,retn,strings.Join(garglist,", "),retnparen))
//4. Go wrapper functions for superclass methods
if !sub { continue } // for subclasses only
grtype := m.Type.GoType()
if grtype == "Void" {
grtype = ""
}
if types.IsGoInterface(grtype) {
grtype = "*Id"
}
if grtype == "BOOL" {
grtype = "bool"
}
if sub {
gocode.WriteString(fmt.Sprintf(`
func (o *%s) Super%s(%s) %s {
`,gname,gnames[i],strings.Join(earglist[1:],", "), grtype))
ns,tps,_ := w.gpntp(m)
lparm := len(tps)-1
if len(tps) > 0 && tps[lparm].Variadic {
vn := ns[lparm]
vn = vn[:len(vn)-1]
ns[lparm] = vn
gocode.WriteString(fmt.Sprintf(
` var %s [%d]unsafe.Pointer
for i,o := range %ss {
%s[i] = o.Ptr()
}
`,vn,w.Vaargs,vn,vn))
}
gocode.WriteString(` ` + types.GoToC(dname + "_super_"+m.Name,ns,m.Type,tps,false) + "\n}\n")
}
}
w.cCode.WriteString(cprotos.String())
w.cCode.WriteString(ccode.String())
@ -1129,6 +1310,8 @@ func (w *Wrapper) Wrap(toproc []string) {
}
fmt.Printf("Writing output to %s\n",path.Join(w.Package,"main.go"))
pInterfaces := map[string]*Interface{}
//Note: the following code eliminates duplicates, so it is acceptable
//to have duplicate interfaces in 'toproc'
for _,iface := range toproc {
pInterfaces[iface] = w.Interfaces[iface]
}
@ -1193,6 +1376,9 @@ void*
for n,p := range w.Delegates {
w.ProcessDelegate(n,p)
}
for n,s := range w.Subclasses {
w.ProcessSubclass(n,s)
}
fmt.Printf("%d functions\n", len(w.Functions))
fmt.Printf("%d enums\n", len(w.NamedEnums) + len(w.AnonEnums))
of.WriteString("package " + w.Package + "\n\n")