Complete the Delegates wrapper. Disambiguate polymorphic methods.
Bluetooth example is now a functioning heart rate monitor. Additional bug fixes in Go types (instances where *Id needs to be used instead of NSObject).
This commit is contained in:
parent
0de9249e6a
commit
dcb7105fca
|
@ -16,6 +16,10 @@ func shouldTerminate(s *ns.NSApplication) ns.NSApplicationTerminateReply {
|
||||||
return ns.NSTerminateNow
|
return ns.NSTerminateNow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldTerminateAfterLastWindowClosed(s *ns.NSApplication) ns.BOOL {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
func willTerminate(n *ns.NSNotification) {
|
func willTerminate(n *ns.NSNotification) {
|
||||||
fmt.Println("Go: will terminate")
|
fmt.Println("Go: will terminate")
|
||||||
}
|
}
|
||||||
|
@ -34,6 +38,7 @@ func app() {
|
||||||
del := ns.AppDelegateAlloc()
|
del := ns.AppDelegateAlloc()
|
||||||
del.ApplicationDidFinishLaunchingCallback(didFinishLaunching)
|
del.ApplicationDidFinishLaunchingCallback(didFinishLaunching)
|
||||||
del.ApplicationShouldTerminateCallback(shouldTerminate)
|
del.ApplicationShouldTerminateCallback(shouldTerminate)
|
||||||
|
del.ApplicationShouldTerminateAfterLastWindowClosedCallback(shouldTerminateAfterLastWindowClosed)
|
||||||
del.ApplicationWillTerminateCallback(willTerminate)
|
del.ApplicationWillTerminateCallback(willTerminate)
|
||||||
del.ApplicationDidBecomeActiveCallback(didBecomeActive)
|
del.ApplicationDidBecomeActiveCallback(didBecomeActive)
|
||||||
a.SetDelegate(del)
|
a.SetDelegate(del)
|
||||||
|
@ -41,7 +46,7 @@ func app() {
|
||||||
//Set up an NSWindow
|
//Set up an NSWindow
|
||||||
w := ns.NSWindowAlloc().InitWithContentRect(
|
w := ns.NSWindowAlloc().InitWithContentRect(
|
||||||
ns.NSMakeRect(200,200,600,600),
|
ns.NSMakeRect(200,200,600,600),
|
||||||
ns.NSWindowStyleMaskTitled,
|
ns.NSWindowStyleMaskTitled | ns.NSWindowStyleMaskClosable,
|
||||||
ns.NSBackingStoreBuffered,
|
ns.NSBackingStoreBuffered,
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
|
|
|
@ -3,7 +3,9 @@ package main
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
"gitlab.wow.st/gmp/nswrap/examples/bluetooth/ns"
|
"gitlab.wow.st/gmp/nswrap/examples/bluetooth/ns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,23 +24,109 @@ 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),nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
|
||||||
|
fmt.Printf("Did discover peripheral\n")
|
||||||
|
c.StopScan()
|
||||||
|
peripheral = p
|
||||||
|
peripheral.Retain()
|
||||||
|
c.ConnectPeripheral(p,nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
||||||
|
fmt.Printf("Did connect peripheral\n")
|
||||||
|
p.SetDelegate(cd)
|
||||||
|
p.DiscoverServices(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func discoverServices(p *ns.CBPeripheral, e *ns.NSError) {
|
||||||
|
fmt.Printf("Did discover services\n")
|
||||||
|
p.Services().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
||||||
|
serv := o.CBService()
|
||||||
|
switch {
|
||||||
|
case serv.UUID().IsEqualTo(hrm_uuid):
|
||||||
|
fmt.Printf("--heart rate monitor service\n")
|
||||||
|
p.DiscoverCharacteristics(nil,serv)
|
||||||
|
case serv.UUID().IsEqualTo(ns.CBUUIDWithGoString("180A")):
|
||||||
|
fmt.Printf("--device information service\n")
|
||||||
|
p.DiscoverCharacteristics(nil,serv)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func hr(d *ns.NSData) int {
|
||||||
|
var x []byte
|
||||||
|
if l := int(d.Length()); l < 4 {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
bs := d.Bytes()
|
||||||
|
x = make([]byte,l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
x[i] = *(*byte)(unsafe.Pointer(uintptr(bs) + uintptr(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var hr int
|
||||||
|
flags := x[0]
|
||||||
|
if flags & 0x80 != 0 { // uint16 format
|
||||||
|
hr = int(binary.BigEndian.Uint16(x[1:2]))
|
||||||
|
} else {
|
||||||
|
hr = int(x[1])
|
||||||
|
}
|
||||||
|
return hr
|
||||||
|
}
|
||||||
|
|
||||||
|
func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) {
|
||||||
|
fmt.Printf("Did discover characteristics\n")
|
||||||
|
fmt.Printf("----%s\n",s.UUID().UUIDString().UTF8String())
|
||||||
|
if s.UUID().IsEqualTo(hrm_uuid) {
|
||||||
|
s.Characteristics().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
||||||
|
chr := o.CBCharacteristic()
|
||||||
|
fmt.Printf("------%s\n",chr.UUID().UUIDString().UTF8String())
|
||||||
|
if chr.UUID().IsEqualTo(hrv_uuid) {
|
||||||
|
p.SetNotifyValue(1,chr)
|
||||||
|
v := chr.Value()
|
||||||
|
fmt.Println(hr(v))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
||||||
|
if chr.UUID().IsEqualTo(hrv_uuid) {
|
||||||
|
v := chr.Value()
|
||||||
|
fmt.Printf("Heart rate: %d\n",hr(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
hrm_uuid *ns.CBUUID
|
||||||
|
hrv_uuid *ns.CBUUID
|
||||||
|
cd *ns.BleDelegate
|
||||||
cm *ns.CBCentralManager
|
cm *ns.CBCentralManager
|
||||||
|
peripheral *ns.CBPeripheral
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
queue := ns.DispatchQueueCreate(ns.CharWithGoString("st.wow.gitlab.ble"),nil)
|
queue := ns.DispatchQueueCreate(ns.CharWithGoString("st.wow.gitlab.ble"),nil)
|
||||||
|
|
||||||
cd := ns.BleDelegateAlloc()
|
cd = ns.BleDelegateAlloc()
|
||||||
cd.CentralManagerDidUpdateStateCallback(updateState)
|
cd.CentralManagerDidUpdateStateCallback(updateState)
|
||||||
|
cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral)
|
||||||
|
cd.CentralManagerDidConnectPeripheralCallback(connectPeripheral)
|
||||||
|
cd.PeripheralDidDiscoverServicesCallback(discoverServices)
|
||||||
|
cd.PeripheralDidDiscoverCharacteristicsForServiceCallback(discoverCharacteristics)
|
||||||
|
cd.PeripheralDidUpdateValueForCharacteristicCallback(updateValue)
|
||||||
|
|
||||||
|
hrm_uuid = ns.CBUUIDWithGoString("180D")
|
||||||
|
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
||||||
|
|
||||||
cm = ns.CBCentralManagerAlloc()
|
cm = ns.CBCentralManagerAlloc()
|
||||||
cm.InitWithDelegate(cd,queue,nil)
|
cm.InitWithDelegate(cd,queue,nil)
|
||||||
|
|
||||||
uuid := ns.CBUUIDWithGoString("180d")
|
|
||||||
_ = uuid
|
|
||||||
select { }
|
select { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,26 +3,24 @@ inputfiles:
|
||||||
- /System/Library/Frameworks/CoreBluetooth.framework/Headers/CoreBluetooth.h
|
- /System/Library/Frameworks/CoreBluetooth.framework/Headers/CoreBluetooth.h
|
||||||
|
|
||||||
classes:
|
classes:
|
||||||
- ble_delegate
|
- NSObject
|
||||||
|
- NSData
|
||||||
- CBManager
|
- CBManager
|
||||||
- CBCentralManager
|
- CBCentralManager
|
||||||
- CBPeripheralManager
|
- CBPeripheralManager
|
||||||
- CBPeripheral
|
- CBPeripheral
|
||||||
- CBCentral
|
- CBCentral
|
||||||
- CBService
|
- CBService
|
||||||
|
- CBAttribute
|
||||||
- CBCharacteristic
|
- CBCharacteristic
|
||||||
- CBDescriptor
|
- CBDescriptor
|
||||||
- CBError
|
- CBError
|
||||||
- CBUUID
|
- CBUUID
|
||||||
- CBAdvertisementData
|
- CBAdvertisementData
|
||||||
- CBATTRequest
|
|
||||||
- NSArray
|
- NSArray
|
||||||
- NSMutableArray
|
- NSMutableArray
|
||||||
- NSDictionary
|
- NSDictionary
|
||||||
- NSEnumerator
|
- NSEnumerator
|
||||||
- NSSet
|
|
||||||
- NSDate
|
|
||||||
- NSTimeZone
|
|
||||||
- NSString
|
- NSString
|
||||||
|
|
||||||
functions: [ NSMakeRange, dispatch_queue_create ]
|
functions: [ NSMakeRange, dispatch_queue_create ]
|
||||||
|
|
56
wrap/main.go
56
wrap/main.go
|
@ -26,6 +26,7 @@ type Wrapper struct {
|
||||||
Protocols map[string]*Protocol
|
Protocols map[string]*Protocol
|
||||||
|
|
||||||
cgoFlags strings.Builder // put cGo directives here
|
cgoFlags strings.Builder // put cGo directives here
|
||||||
|
cImports strings.Builder // put c imports and sysimports here
|
||||||
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
|
||||||
goConst strings.Builder // put Go constants (from C enums) here
|
goConst strings.Builder // put Go constants (from C enums) here
|
||||||
|
@ -63,20 +64,20 @@ func (w *Wrapper) Frameworks(ss []string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _,s := range ss {
|
for _,s := range ss {
|
||||||
w.cgoFlags.WriteString(fmt.Sprintf("#import <%s/%s.h>\n",s,s))
|
w.cImports.WriteString(fmt.Sprintf("#import <%s/%s.h>\n",s,s))
|
||||||
}
|
}
|
||||||
w.cgoFlags.WriteString("#cgo LDFLAGS: -framework " + strings.Join(ss," -framework "))
|
w.cgoFlags.WriteString("#cgo LDFLAGS: -framework " + strings.Join(ss," -framework "))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) Import(ss []string) {
|
func (w *Wrapper) Import(ss []string) {
|
||||||
for _,s := range ss {
|
for _,s := range ss {
|
||||||
w.cgoFlags.WriteString("\n#import \"" + s + "\"\n")
|
w.cImports.WriteString("\n#import \"" + s + "\"\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) SysImport(ss []string) {
|
func (w *Wrapper) SysImport(ss []string) {
|
||||||
for _,s := range ss {
|
for _,s := range ss {
|
||||||
w.cgoFlags.WriteString("\n#import <" + s + ">\n")
|
w.cImports.WriteString("\n#import <" + s + ">\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +117,7 @@ type Enum struct {
|
||||||
type Protocol struct {
|
type Protocol struct {
|
||||||
Name, GoName string
|
Name, GoName string
|
||||||
Methods map[string]*Method
|
Methods map[string]*Method
|
||||||
Polymorphic map[string]bool
|
Polymorphic map[string]int
|
||||||
}
|
}
|
||||||
|
|
||||||
//isVoid() returns true if the method has no return value.
|
//isVoid() returns true if the method has no return value.
|
||||||
|
@ -291,7 +292,7 @@ func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
|
||||||
Name: n.Name,
|
Name: n.Name,
|
||||||
GoName: types.NewTypeFromString(n.Name,n.Name).GoType(),
|
GoName: types.NewTypeFromString(n.Name,n.Name).GoType(),
|
||||||
Methods: map[string]*Method{},
|
Methods: map[string]*Method{},
|
||||||
Polymorphic: map[string]bool{},
|
Polymorphic: map[string]int{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _,c := range n.Children() {
|
for _,c := range n.Children() {
|
||||||
|
@ -307,10 +308,19 @@ func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
|
||||||
var avail bool
|
var avail bool
|
||||||
m.Parameters, avail = w.GetParms(x,p.Name)
|
m.Parameters, avail = w.GetParms(x,p.Name)
|
||||||
if avail {
|
if avail {
|
||||||
if p.Methods[m.Name] != nil {
|
pname := strings.Title(m.Name)
|
||||||
p.Polymorphic[m.Name] = true
|
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)
|
||||||
|
p.Methods[pname2] = m2
|
||||||
|
delete(p.Methods,m.Name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.Polymorphic[m.Name] = 1
|
||||||
}
|
}
|
||||||
p.Methods[m.Name] = m
|
p.Methods[pname] = m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -862,9 +872,6 @@ const %s %s= C.%s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME: need to disambiguate polymorphic method names. Something like:
|
|
||||||
//func Disambiguate([]*Method) []*Method {} ...
|
|
||||||
//Can allow user to decide on a disambiguation strategy
|
|
||||||
//NOTE: The delegate wrapper does not support variadic callback functions.
|
//NOTE: The delegate wrapper does not support variadic callback functions.
|
||||||
func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
|
func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
|
||||||
//To create (per delegate):
|
//To create (per delegate):
|
||||||
|
@ -884,6 +891,7 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
|
||||||
|
|
||||||
//set up array of methods for this delegate
|
//set up array of methods for this delegate
|
||||||
methods := []*Method{}
|
methods := []*Method{}
|
||||||
|
gnames := []string{} // go names for methods
|
||||||
for _,pname := range ps {
|
for _,pname := range ps {
|
||||||
proto := w.Protocols[pname]
|
proto := w.Protocols[pname]
|
||||||
if proto == nil {
|
if proto == nil {
|
||||||
|
@ -891,18 +899,16 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
fmt.Printf(" proto %s\n",pname)
|
fmt.Printf(" proto %s\n",pname)
|
||||||
for _,m := range proto.Methods {
|
for gname,m := range proto.Methods {
|
||||||
if proto.Polymorphic[m.Name] {
|
if m.Type.IsFunction() || m.Type.IsFunctionPtr() || m.hasFunctionParam() {
|
||||||
//FIXME: skip polymorphic methods for now
|
|
||||||
fmt.Printf(" Skipping polymorphic method '%s'\n",m.Name)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
methods = append(methods,m)
|
methods = append(methods,m)
|
||||||
|
gnames = append(gnames,gname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
methprotos := make([]string,len(methods)) // objc method prototypes
|
methprotos := make([]string,len(methods)) // objc method prototypes
|
||||||
gnames := make([]string,len(methods)) // go names for methods
|
|
||||||
gname := strings.Title(dname) // go name for this Delegate
|
gname := strings.Title(dname) // go name for this Delegate
|
||||||
vnames := make([][]string,len(methods)) // objc variable names
|
vnames := make([][]string,len(methods)) // objc variable names
|
||||||
gtypes := make([][]string,len(methods)) // go parameter types for each method
|
gtypes := make([][]string,len(methods)) // go parameter types for each method
|
||||||
|
@ -952,7 +958,6 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
|
||||||
}
|
}
|
||||||
methprotos[i] = fmt.Sprintf(
|
methprotos[i] = fmt.Sprintf(
|
||||||
`- (%s)%s%s;`,m.Type.Node.Ctype(),m.Name,parms)
|
`- (%s)%s%s;`,m.Type.Node.Ctype(),m.Name,parms)
|
||||||
gnames[i] = strings.Title(m.Name)
|
|
||||||
if x := m.Type.GoType(); x == "Void" {
|
if x := m.Type.GoType(); x == "Void" {
|
||||||
grtypes[i] = ""
|
grtypes[i] = ""
|
||||||
} else {
|
} else {
|
||||||
|
@ -1061,8 +1066,12 @@ func (d *%s) %sCallback(f func(%s)%s) {
|
||||||
garglist := []string{}
|
garglist := []string{}
|
||||||
for j := 1; j < len(vnames[i]); j++ {
|
for j := 1; j < len(vnames[i]); j++ {
|
||||||
earglist = append(earglist,vnames[i][j] + " " + getypes[i][j])
|
earglist = append(earglist,vnames[i][j] + " " + getypes[i][j])
|
||||||
|
gt2 := gtypes[i][j-1]
|
||||||
|
if types.IsGoInterface(gt2) {
|
||||||
|
gt2 = "*Id"
|
||||||
|
}
|
||||||
garglist = append(garglist,fmt.Sprintf(
|
garglist = append(garglist,fmt.Sprintf(
|
||||||
`(%s)(%s)`,gtypes[i][j-1],vnames[i][j]))
|
`(%s)(%s)`,gt2,vnames[i][j]))
|
||||||
}
|
}
|
||||||
retdecl := ""
|
retdecl := ""
|
||||||
retname := ""
|
retname := ""
|
||||||
|
@ -1090,7 +1099,6 @@ func %s%s(%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,retn,strings.Join(garglist,", "),retnparen))
|
||||||
}
|
}
|
||||||
//DEBUG
|
|
||||||
w.cCode.WriteString(cprotos.String())
|
w.cCode.WriteString(cprotos.String())
|
||||||
w.cCode.WriteString(ccode.String())
|
w.cCode.WriteString(ccode.String())
|
||||||
w.goTypes.WriteString(gotypes.String())
|
w.goTypes.WriteString(gotypes.String())
|
||||||
|
@ -1098,6 +1106,7 @@ func %s%s(%s)%s {
|
||||||
w.goExports.WriteString(goexports.String())
|
w.goExports.WriteString(goexports.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (w *Wrapper) Wrap(toproc []string) {
|
func (w *Wrapper) Wrap(toproc []string) {
|
||||||
if w.Package == "" { w.Package = "ns" }
|
if w.Package == "" { w.Package = "ns" }
|
||||||
err := os.MkdirAll(w.Package,0755)
|
err := os.MkdirAll(w.Package,0755)
|
||||||
|
@ -1125,6 +1134,11 @@ func (w *Wrapper) Wrap(toproc []string) {
|
||||||
if i == nil {
|
if i == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
w.processType(types.NewTypeFromString(i.GoName,""))
|
||||||
|
gname := i.GoName
|
||||||
|
if types.IsGoInterface(i.GoName) {
|
||||||
|
gname = "Id"
|
||||||
|
}
|
||||||
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
||||||
i.Name, len(i.Properties), len(i.Methods))
|
i.Name, len(i.Properties), len(i.Methods))
|
||||||
|
|
||||||
|
@ -1132,7 +1146,7 @@ func (w *Wrapper) Wrap(toproc []string) {
|
||||||
func %sAlloc() *%s {
|
func %sAlloc() *%s {
|
||||||
return (*%s)(unsafe.Pointer(C.%sAlloc()))
|
return (*%s)(unsafe.Pointer(C.%sAlloc()))
|
||||||
}
|
}
|
||||||
`,i.GoName,i.GoName,i.GoName,i.Name))
|
`,i.GoName,gname,gname,i.Name))
|
||||||
|
|
||||||
if i.Name != "NSAutoreleasePool" {
|
if i.Name != "NSAutoreleasePool" {
|
||||||
w.cCode.WriteString(fmt.Sprintf(`
|
w.cCode.WriteString(fmt.Sprintf(`
|
||||||
|
@ -1183,6 +1197,8 @@ void*
|
||||||
|
|
||||||
of.WriteString(w.cgoFlags.String() + "\n")
|
of.WriteString(w.cgoFlags.String() + "\n")
|
||||||
ef.WriteString(w.cgoFlags.String() + "\n")
|
ef.WriteString(w.cgoFlags.String() + "\n")
|
||||||
|
of.WriteString(w.cImports.String() + "\n")
|
||||||
|
ef.WriteString(w.cImports.String() + "\n")
|
||||||
|
|
||||||
of.WriteString(w.cCode.String())
|
of.WriteString(w.cCode.String())
|
||||||
of.WriteString(`
|
of.WriteString(`
|
||||||
|
|
Loading…
Reference in New Issue
Block a user