More work.
This commit is contained in:
parent
eef149060f
commit
90669b9c7f
14
interop.h
14
interop.h
|
@ -1,14 +0,0 @@
|
||||||
// 11 december 2015
|
|
||||||
|
|
||||||
#ifndef __UI_INTEROP_H__
|
|
||||||
#define __UI_INTEROP_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern char *interopInit(void);
|
|
||||||
extern void interopFreeStr(char *);
|
|
||||||
extern void interopRun(void);
|
|
||||||
extern void interopQuit(void);
|
|
||||||
extern void interopQueueMain(uintptr_t);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -5,4 +5,5 @@
|
||||||
|
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
// #cgo LDFLAGS: -L. -lui -lpthread
|
// #cgo LDFLAGS: -L${SRCDIR} -lui -Wl,-rpath=$ORIGIN
|
||||||
|
import "C"
|
||||||
|
|
59
main.go
59
main.go
|
@ -3,10 +3,20 @@
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// #include "interop.h"
|
// #include "ui.h"
|
||||||
|
// extern void doQueued(void *);
|
||||||
|
// /* I forgot how dumb cgo is... ./main.go:73: cannot use _Cgo_ptr(_Cfpvar_fp_doQueued) (type unsafe.Pointer) as type *[0]byte in argument to _Cfunc_uiQueueMain */
|
||||||
|
// /* I'm pretty sure this worked before... */
|
||||||
|
// static inline void realQueueMain(void *x)
|
||||||
|
// {
|
||||||
|
// uiQueueMain(doQueued, x);
|
||||||
|
// }
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
// Main initializes package ui, runs f to set up the program,
|
// Main initializes package ui, runs f to set up the program,
|
||||||
|
@ -23,23 +33,35 @@ func Main(f func()) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func start(errchan chan error, f func()) {
|
func start(errchan chan error, f func()) {
|
||||||
estr := C.interopInit()
|
runtime.LockOSThread()
|
||||||
if estr != "" {
|
|
||||||
|
// TODO HEAP SAFETY
|
||||||
|
opts := C.uiInitOptions{}
|
||||||
|
estr := C.uiInit(&opts)
|
||||||
|
if estr != nil {
|
||||||
errchan <- errors.New(C.GoString(estr))
|
errchan <- errors.New(C.GoString(estr))
|
||||||
C.interopFreeStr(estr)
|
C.uiFreeInitError(estr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
QueueMain(f)
|
QueueMain(f)
|
||||||
C.interopRun()
|
C.uiMain()
|
||||||
errchan <- nil
|
errchan <- nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit queues an exit from the GUI thread. It does not exit the
|
// Quit queues an exit from the GUI thread. It does not exit the
|
||||||
// program. Quit must be called from the GUI thread.
|
// program. Quit must be called from the GUI thread.
|
||||||
func Quit() {
|
func Quit() {
|
||||||
C.interopQuit()
|
C.uiQuit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These prevent the passing of Go functions into C land.
|
||||||
|
// TODO make an actual sparse list instead of this monotonic map thingy
|
||||||
|
var (
|
||||||
|
qmmap = make(map[uintptr]func())
|
||||||
|
qmcurrent = uintptr(0)
|
||||||
|
qmlock sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
// QueueMain queues f to be executed on the GUI thread when
|
// QueueMain queues f to be executed on the GUI thread when
|
||||||
// next possible. It returns immediately; that is, it does not wait
|
// next possible. It returns immediately; that is, it does not wait
|
||||||
// for the function to actually be executed. QueueMain is the only
|
// for the function to actually be executed. QueueMain is the only
|
||||||
|
@ -48,13 +70,26 @@ func Quit() {
|
||||||
// goroutines and the GUI thread. Calling QueueMain after Quit
|
// goroutines and the GUI thread. Calling QueueMain after Quit
|
||||||
// has been called results in undefined behavior.
|
// has been called results in undefined behavior.
|
||||||
func QueueMain(f func()) {
|
func QueueMain(f func()) {
|
||||||
n := interoperAdd(f)
|
qmlock.Lock()
|
||||||
C.interopQueueMain(n)
|
defer qmlock.Unlock()
|
||||||
|
|
||||||
|
n := qmcurrent
|
||||||
|
qmcurrent++
|
||||||
|
qmmap[n] = f
|
||||||
|
C.realQueueMain(unsafe.Pointer(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
//export interopDoQueued
|
//export doQueued
|
||||||
func interopDoQueued(n C.uintptr_t) {
|
func doQueued(nn unsafe.Pointer) {
|
||||||
ff := interoperTake(n)
|
qmlock.Lock()
|
||||||
f := ff.(func())
|
|
||||||
|
n := uintptr(nn)
|
||||||
|
f := qmmap[n]
|
||||||
|
delete(qmmap, n)
|
||||||
|
|
||||||
|
// allow uiQueueMain() to be called by a queued function
|
||||||
|
// TODO explicitly allow this in libui too
|
||||||
|
qmlock.Unlock()
|
||||||
|
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
This directory contains the pre-libui package ui and its various development files. They will be removed at a later date. Do not use this package.
|
Loading…
Reference in New Issue