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
|
||||
|
||||
// #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
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"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"
|
||||
|
||||
// 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()) {
|
||||
estr := C.interopInit()
|
||||
if estr != "" {
|
||||
runtime.LockOSThread()
|
||||
|
||||
// TODO HEAP SAFETY
|
||||
opts := C.uiInitOptions{}
|
||||
estr := C.uiInit(&opts)
|
||||
if estr != nil {
|
||||
errchan <- errors.New(C.GoString(estr))
|
||||
C.interopFreeStr(estr)
|
||||
C.uiFreeInitError(estr)
|
||||
return
|
||||
}
|
||||
QueueMain(f)
|
||||
C.interopRun()
|
||||
C.uiMain()
|
||||
errchan <- nil
|
||||
}
|
||||
|
||||
// Quit queues an exit from the GUI thread. It does not exit the
|
||||
// program. Quit must be called from the GUI thread.
|
||||
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
|
||||
// next possible. It returns immediately; that is, it does not wait
|
||||
// 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
|
||||
// has been called results in undefined behavior.
|
||||
func QueueMain(f func()) {
|
||||
n := interoperAdd(f)
|
||||
C.interopQueueMain(n)
|
||||
qmlock.Lock()
|
||||
defer qmlock.Unlock()
|
||||
|
||||
n := qmcurrent
|
||||
qmcurrent++
|
||||
qmmap[n] = f
|
||||
C.realQueueMain(unsafe.Pointer(n))
|
||||
}
|
||||
|
||||
//export interopDoQueued
|
||||
func interopDoQueued(n C.uintptr_t) {
|
||||
ff := interoperTake(n)
|
||||
f := ff.(func())
|
||||
//export doQueued
|
||||
func doQueued(nn unsafe.Pointer) {
|
||||
qmlock.Lock()
|
||||
|
||||
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()
|
||||
}
|
||||
|
|
|
@ -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