mirror of
https://github.com/bluszcz/cutego.git
synced 2024-09-28 13:15:17 +03:00
cgo-less interop related changes
This commit is contained in:
parent
550ceb9a59
commit
494d2f8c1e
9 changed files with 90 additions and 27 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,6 +9,7 @@
|
|||
*.vagrant
|
||||
.DS_Store
|
||||
Mfile*
|
||||
qtbox
|
||||
|
||||
*/*-minimal.*
|
||||
*/*.o
|
||||
|
|
20
README.md
20
README.md
|
@ -5,11 +5,11 @@ Introduction
|
|||
|
||||
[Go](https://en.wikipedia.org/wiki/Go_(programming_language)), also known as Golang, is a programming language designed at Google.
|
||||
|
||||
[therecipe/qt](https://github.com/therecipe/qt) allows you to write Qt applications entirely in Go or JavaScript.
|
||||
[therecipe/qt](https://github.com/therecipe/qt) allows you to write Qt applications entirely in Go, [JavaScript/TypeScript](https://github.com/therecipe/entry), [Dart/Flutter](https://github.com/therecipe/flutter), [Haxe](https://github.com/therecipe/haxe) and [Swift](https://github.com/therecipe/swift)
|
||||
|
||||
Beside the language bindings provided, `therecipe/qt` also greatly simplifies the deployment of Qt applications to various software and hardware platforms.
|
||||
|
||||
At the time of writing, almost all Qt functions and classes are accessible from Go and JavaScript, and you should be able to find everything you need to build fully featured Qt applications.
|
||||
At the time of writing, almost all Qt functions and classes are accessible, and you should be able to find everything you need to build fully featured Qt applications.
|
||||
|
||||
Impressions
|
||||
-----------
|
||||
|
@ -23,6 +23,22 @@ Installation
|
|||
|
||||
The following instructions assume that you already installed [Go](https://golang.org/dl/) and [Git](https://git-scm.com/downloads)
|
||||
|
||||
#### (Experimental) cgo-less version (try this first, if you are new and want to test this binding)
|
||||
|
||||
##### Windows
|
||||
|
||||
```powershell
|
||||
go get -ldflags="-w" github.com/therecipe/examples/basic/widgets && for /f %v in ('go env GOPATH') do %v\bin\widgets.exe
|
||||
```
|
||||
|
||||
##### macOS/Linux
|
||||
|
||||
```bash
|
||||
go get -ldflags="-w" github.com/therecipe/examples/basic/widgets && $(go env GOPATH)/bin/widgets
|
||||
```
|
||||
|
||||
#### Default version
|
||||
|
||||
##### Windows [(more info)](https://github.com/therecipe/qt/wiki/Installation-on-Windows)
|
||||
|
||||
```powershell
|
||||
|
|
|
@ -95,6 +95,23 @@ func goFunctionBody(function *parser.Function) string {
|
|||
|
||||
default:
|
||||
|
||||
//TODO:
|
||||
if class.IsSubClassOf("QCoreApplication") {
|
||||
if function.Meta == parser.CONSTRUCTOR {
|
||||
return fmt.Sprintf("\ngow.InitProcess()\nreturn New%vFromPointer(%vQCoreApplication_Instance().Pointer())", class.Name, func() string {
|
||||
if goModule(class.Module) != "core" {
|
||||
return "core."
|
||||
}
|
||||
return ""
|
||||
}())
|
||||
}
|
||||
|
||||
if function.Name == "exec" {
|
||||
return "\ngow.Exec()\nreturn 0"
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
var input []string
|
||||
for _, p := range function.Parameters {
|
||||
input = append(input, parser.CleanName(p.Name, p.Value))
|
||||
|
@ -110,7 +127,9 @@ func goFunctionBody(function *parser.Function) string {
|
|||
ret_pre = "return "
|
||||
ret_suf = fmt.Sprintf(".(%v)", out)
|
||||
|
||||
if strings.Contains(ret_suf, "__") && !strings.Contains(ret_suf, "[") { //TODO: support for slices and maps containing enums
|
||||
//TODO: is there some better way ?
|
||||
//TODO: support for slices and maps as well
|
||||
if (strings.Contains(ret_suf, "__") || strings.HasPrefix(ret_suf, ".(int") || strings.HasPrefix(ret_suf, ".(uint")) && !strings.Contains(ret_suf, "[") {
|
||||
ret_pre += out + "("
|
||||
ret_suf = ".(float64))"
|
||||
}
|
||||
|
|
|
@ -1456,7 +1456,7 @@ import "C"
|
|||
|
||||
var dartInput []string
|
||||
fmt.Fprint(bb, "import (\n")
|
||||
for _, m := range append(parser.GetLibs(), "qt", "strings", "unsafe", "log", "runtime", "fmt", "errors", "js", "time", "hex", "reflect", "math", "sync", "strconv", "internal") {
|
||||
for _, m := range append(parser.GetLibs(), "qt", "strings", "unsafe", "log", "runtime", "fmt", "errors", "js", "time", "hex", "reflect", "math", "sync", "strconv", "internal", "gow") {
|
||||
mlow := strings.ToLower(m)
|
||||
if strings.Contains(inputString, fmt.Sprintf(" %v.", mlow)) ||
|
||||
strings.Contains(inputString, fmt.Sprintf("\t%v.", mlow)) ||
|
||||
|
@ -1480,6 +1480,9 @@ import "C"
|
|||
case "internal":
|
||||
fmt.Fprintln(bb, "\"github.com/therecipe/qt/internal\"")
|
||||
|
||||
case "gow":
|
||||
fmt.Fprintln(bb, "\"github.com/therecipe/qt/interop/gow\"")
|
||||
|
||||
case "js":
|
||||
if parser.UseWasm() {
|
||||
fmt.Fprintln(bb, "\"syscall/js\"")
|
||||
|
|
|
@ -289,7 +289,7 @@ func Minimal(path, target, tags string, skipSetup bool) {
|
|||
if utils.QT_STATIC() {
|
||||
exportClass(parser.State.ClassMap["QSvgWidget"], files)
|
||||
}
|
||||
if utils.QT_FELGO() {
|
||||
if utils.QT_FELGO() || utils.QT_GEN_GO_WRAPPER() {
|
||||
exportClass(parser.State.ClassMap["QCoreApplication"], files)
|
||||
exportFunction(parser.State.ClassMap["QCoreApplication"].GetFunction("instance"), files)
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ func Check(target string, docker, vagrant bool) {
|
|||
{"QT_QMAKE_DIR", utils.QT_QMAKE_DIR()},
|
||||
{"QT_WEBKIT", fmt.Sprint(utils.QT_WEBKIT())},
|
||||
{"QT_STATIC", fmt.Sprint(utils.QT_STATIC())},
|
||||
{"QT_GEN_TSD", fmt.Sprint(utils.QT_GEN_TSD())},
|
||||
{"QT_GEN_GO", fmt.Sprint(utils.QT_GEN_GO_WRAPPER())},
|
||||
{"QT_GEN_OPENGL", fmt.Sprint(utils.QT_GEN_OPENGL())},
|
||||
{"QT_GEN_QUICK_EXTRAS", fmt.Sprint(utils.QT_GEN_QUICK_EXTRAS())},
|
||||
{"QT_RESOURCES_BIG", fmt.Sprint(utils.QT_RESOURCES_BIG())},
|
||||
|
|
|
@ -36,7 +36,7 @@ func Generate(target string, docker, vagrant bool) {
|
|||
mode = "stub"
|
||||
}
|
||||
|
||||
if target == "windows" && runtime.GOOS == target {
|
||||
if target == "windows" && runtime.GOOS == target && os.Getenv("QT_DEBUG_CONSOLE") != "false" {
|
||||
os.Setenv("QT_DEBUG_CONSOLE", "true")
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,7 @@ func Generate(target string, docker, vagrant bool) {
|
|||
}
|
||||
utils.Log.Infof("generating %v qt/%v%v", mode, strings.ToLower(module), license)
|
||||
|
||||
if target == runtime.GOOS || utils.QT_FAT() || (mode == "full" && (target == "js" || target == "wasm")) ||
|
||||
(utils.QT_STATIC() || utils.QT_MXE_STATIC()) && utils.QT_DOCKER() { //TODO: REVIEW
|
||||
if target == runtime.GOOS || utils.QT_FAT() || (mode == "full" && (target == "js" || target == "wasm")) { //TODO: REVIEW
|
||||
templater.GenModule(module, target, templater.NONE)
|
||||
} else {
|
||||
templater.CgoTemplate(module, "", target, templater.MINIMAL, "", "") //TODO: collect errors
|
||||
|
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
template: docker_showcase_template.yml
|
||||
parameters:
|
||||
tag: box
|
||||
# dep: windows_64_static
|
||||
dep: windows_64_shared_wine
|
||||
-
|
||||
template: docker_windows_ci_template.yml
|
||||
parameters:
|
||||
|
|
|
@ -62,13 +62,15 @@ func handleCallback(message string) string {
|
|||
var msg []interface{}
|
||||
json.Unmarshal([]byte(message), &msg)
|
||||
|
||||
meth := reflect.ValueOf(callbackTable[uintptr(msg[0].(float64))][msg[1].(string)])
|
||||
|
||||
rv := make([]reflect.Value, len(msg)-2)
|
||||
for i, v := range convertList(msg[2:]) {
|
||||
rv[i] = reflect.ValueOf(v)
|
||||
rv[i] = reflect.ValueOf(v).Convert(meth.Type().In(i))
|
||||
}
|
||||
|
||||
var output []byte
|
||||
if ret := reflect.ValueOf(callbackTable[uintptr(msg[0].(float64))][msg[1].(string)]).Call(rv); len(ret) > 0 {
|
||||
if ret := meth.Call(rv); len(ret) > 0 {
|
||||
output, _ = json.Marshal(convertToJson(ret[0].Interface()))
|
||||
}
|
||||
|
||||
|
@ -154,17 +156,25 @@ func convertToJson(i interface{}) interface{} {
|
|||
return convertMapToJson(i.(map[string]interface{}))
|
||||
|
||||
case reflect.Slice:
|
||||
return convertListToJson(i.([]interface{}))
|
||||
switch i.(type) {
|
||||
//TODO:
|
||||
case []string:
|
||||
case []uint, []uint8, []uint16, []uint32, []uint64:
|
||||
case []int, []int8, []int16, []int32, []int64:
|
||||
//
|
||||
//case []*qml.QQmlError:
|
||||
|
||||
default:
|
||||
return convertListToJson(i.([]interface{}))
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
return map[string]interface{}{
|
||||
"___pointer": uintptr(reflect.ValueOf(i).MethodByName("Pointer").Call(nil)[0].Interface().(unsafe.Pointer)),
|
||||
"___className": reflect.ValueOf(i).MethodByName("ClassNameInternalF").Call(nil)[0].Interface(),
|
||||
}
|
||||
|
||||
default:
|
||||
return i
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
var inited = false
|
||||
|
@ -222,8 +232,13 @@ var Config = &InteropServerConfig{
|
|||
"",
|
||||
}
|
||||
|
||||
var (
|
||||
proc *exec.Cmd
|
||||
stderr io.ReadCloser
|
||||
)
|
||||
|
||||
// TODO: NewQApplication
|
||||
func InitProcess() (*exec.Cmd, io.ReadCloser) {
|
||||
func InitProcess() {
|
||||
|
||||
var runPath string
|
||||
|
||||
|
@ -258,7 +273,11 @@ func InitProcess() (*exec.Cmd, io.ReadCloser) {
|
|||
|
||||
println("final qtbox location:", runPath)
|
||||
|
||||
if _, err := os.Stat(runPath); err == nil && Config.Override || err != nil {
|
||||
dst := filepath.Dir(runPath)
|
||||
_, err := os.Stat(runPath)
|
||||
_, errF := os.Stat(filepath.Join(dst, "qtbox"))
|
||||
|
||||
if Config.Override || (err != nil && errF != nil) {
|
||||
|
||||
var copyWithProgress = func(w io.Writer, r io.Reader, callback func(off int64)) error {
|
||||
tee := io.TeeReader(r, w)
|
||||
|
@ -306,16 +325,21 @@ func InitProcess() (*exec.Cmd, io.ReadCloser) {
|
|||
fw.Close()
|
||||
} else {
|
||||
|
||||
dst := filepath.Dir(runPath)
|
||||
|
||||
for _, f := range r.File {
|
||||
|
||||
//TODO: pack runtimes with correct name
|
||||
fns := strings.Split(f.Name, "/")
|
||||
fns[0] = "qtbox"
|
||||
f.Name = strings.Join(fns, "/")
|
||||
//
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(filepath.Join(dst, f.Name), f.Mode())
|
||||
continue
|
||||
}
|
||||
|
||||
dn, fn := filepath.Split(f.Name)
|
||||
if strings.HasPrefix(fn, "full") {
|
||||
if strings.HasPrefix(fn, "full") { //TODO: pack runtimes with correct name
|
||||
fn = filepath.Join(dn, "qtbox"+ending)
|
||||
} else {
|
||||
fn = f.Name
|
||||
|
@ -337,8 +361,6 @@ func InitProcess() (*exec.Cmd, io.ReadCloser) {
|
|||
fr.Close()
|
||||
}
|
||||
|
||||
os.Rename(filepath.Join(dst, r.File[0].Name), filepath.Join(dst, "qtbox"))
|
||||
|
||||
runPath = filepath.Join(dst, "qtbox", "qtbox"+ending)
|
||||
}
|
||||
}
|
||||
|
@ -355,13 +377,16 @@ func InitProcess() (*exec.Cmd, io.ReadCloser) {
|
|||
println(err.Error())
|
||||
}
|
||||
process.Start()
|
||||
|
||||
time.Sleep(3 * time.Second) //TODO:
|
||||
return process, rc
|
||||
|
||||
proc = process
|
||||
stderr = rc
|
||||
}
|
||||
|
||||
// TODO: QApplication_Exec
|
||||
func Exec(p *exec.Cmd, rc io.ReadCloser) {
|
||||
scanner := bufio.NewScanner(rc)
|
||||
func Exec() {
|
||||
scanner := bufio.NewScanner(stderr)
|
||||
|
||||
go func() {
|
||||
for scanner.Scan() {
|
||||
|
@ -376,5 +401,5 @@ func Exec(p *exec.Cmd, rc io.ReadCloser) {
|
|||
}
|
||||
}()
|
||||
|
||||
p.Wait()
|
||||
proc.Wait()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue