Skip to content

Commit 1f663c5

Browse files
author
drswinghead
committed
add qtrel package to reduce binary size
1 parent 58034ab commit 1f663c5

File tree

6 files changed

+526
-0
lines changed

6 files changed

+526
-0
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module github.com/kitech/qt.go
22

3+
go 1.15
4+
35
require (
46
github.com/Workiva/go-datastructures v1.0.44 // indirect
57
github.com/bitly/go-simplejson v0.5.0
@@ -9,6 +11,7 @@ require (
911
github.com/emirpasic/gods v1.9.0
1012
github.com/gonuts/dl v0.0.0-20160302100715-9a2e942d3477 // indirect
1113
github.com/huandu/xstrings v1.0.0 // indirect
14+
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639
1215
github.com/kitech/dl v0.0.0-20160302100715-9a2e942d3477
1316
github.com/kitech/goplusplus v0.0.0-20171220130708-3b7427a37be0
1417
github.com/kr/pretty v0.1.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ github.com/gonuts/dl v0.0.0-20160302100715-9a2e942d3477 h1:VTyUIe+mjc/gOrrVRYHPZ
1414
github.com/gonuts/dl v0.0.0-20160302100715-9a2e942d3477/go.mod h1:sJFtK/zMj1tykTU2ImO2VL+7JGn4U7gTiFHt7rYJD+g=
1515
github.com/huandu/xstrings v1.0.0 h1:pO2K/gKgKaat5LdpAhxhluX2GPQMaI3W5FUz/I/UnWk=
1616
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
17+
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=
18+
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
1719
github.com/kitech/dl v0.0.0-20160302100715-9a2e942d3477 h1:d9LQ8IKrFCZFdEPo+FFQhpNnJCZyjvCrSQDbDfTs0YE=
1820
github.com/kitech/dl v0.0.0-20160302100715-9a2e942d3477/go.mod h1:rs/ASGqdrczQbnYVcZ+x5fk+EHouoBevEXKRqGDm8VI=
1921
github.com/kitech/goplusplus v0.0.0-20171220130708-3b7427a37be0 h1:EU69So/2tjEcAWABWuR21TiF0uy1mzIC7FX8d2NlyxU=

qtrel/callcc.go

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
package qtrel
2+
3+
import (
4+
"go/scanner"
5+
"go/token"
6+
"log"
7+
"reflect"
8+
"strings"
9+
"unsafe"
10+
11+
"github.com/ianlancetaylor/demangle"
12+
"github.com/kitech/qt.go/qtrt"
13+
)
14+
15+
const ulpfx = "_ZN"
16+
const culpfx = "C_ZN"
17+
18+
/*
19+
const QStringNew0 = "_ZN7QStringC2Ev"
20+
//const QStringNew1 = "_ZN7QStringC2EPKc"
21+
const QStringLength0 = "_ZNK7QString6lengthEv"
22+
*/
23+
24+
// no this version, for ctor and static member and c function
25+
func CC0(mgname string, args ...interface{}) ccret {
26+
return ccimpl(nil, mgname, args...)
27+
}
28+
29+
// only return pointer
30+
func CC0p(mgname string, args ...interface{}) CObject {
31+
rv := CC0(mgname, args...)
32+
return CObject(rv.Ptr())
33+
}
34+
35+
func ccimpl(cthis unsafe.Pointer, mgname string, args ...interface{}) ccret {
36+
mgname = ulpfx + mgname
37+
cmo := cppfilt(mgname)
38+
argv := convgoargs2c(cmo, args)
39+
if cthis != nil {
40+
argv = append([]interface{}{cthis}, argv...)
41+
_ = argv
42+
}
43+
44+
rv, err := qtrt.InvokeQtFunc6(mgname, qtrt.FFI_TYPE_UINT64, argv...)
45+
// log.Printf("rv=%+v err=%v %s\n", rv, err, mgname)
46+
qtrt.ErrPrint(err)
47+
return newccret(rv, &mgname, cmo)
48+
}
49+
50+
func (this CObject) CC0(mgname string, args ...interface{}) ccret {
51+
return ccimpl(this.Ptr(), mgname, args...)
52+
}
53+
54+
func (this CObject) CC0p(mgname string, args ...interface{}) CObject {
55+
rv := ccimpl(this.Ptr(), mgname, args...)
56+
return rv.Cobj()
57+
}
58+
59+
func Inherit(cbobj qtrt.CObjectITF, mgname string, fn interface{}) {
60+
// cthis unsafe.Pointer
61+
mgname = ulpfx + mgname
62+
cmo := cppfilt(mgname)
63+
qtrt.SetAllInheritCallback(cbobj, cmo.mth, fn)
64+
}
65+
func (this CObject) Inherit(mgname string, fn interface{}) {
66+
// qtrt.SetAllInheritCallback(this, "", fn)
67+
Inherit(this, mgname, fn)
68+
}
69+
70+
func (this CObject) Connect(signal string, slotfn interface{}) {
71+
qtrt.Connect(this, signal, slotfn)
72+
}
73+
func (this CObject) Disconnect(signal string) {
74+
qtrt.Disconnect(this, signal)
75+
}
76+
77+
type CObject uintptr
78+
79+
func (this CObject) GetCthis() unsafe.Pointer { return unsafe.Pointer(this) }
80+
func (this CObject) SetCthis(cthis unsafe.Pointer) {}
81+
func (CObject) FromCthis(cthis unsafe.Pointer) CObject {
82+
return CObject(uintptr(cthis))
83+
}
84+
func (this CObject) Ptr() unsafe.Pointer { return unsafe.Pointer(this) }
85+
86+
// type QObject uintptr
87+
// type QWidget uintptr
88+
89+
var ccrety = reflect.TypeOf(ccret(0))
90+
91+
// assert sizeof(ccret) == sizeof(uintptr)
92+
// TODO how about x86 pointer
93+
type ccret uint64
94+
95+
/*
96+
type ccret struct {
97+
rv uint64
98+
//typ int
99+
}
100+
*/
101+
102+
func newccret(rv uint64, fnsym *string, cmo *cppmethod) ccret {
103+
return ccret(rv)
104+
// return ccret{rv}
105+
//return ccret{rv, 0}
106+
}
107+
108+
func (this ccret) Int() int { return int(this) }
109+
func (this ccret) Uint() uint { return uint(this) }
110+
func (this ccret) I32() int32 { return int32(this) }
111+
func (this ccret) I64() int64 { return int64(this) }
112+
func (this ccret) U32() uint32 { return uint32(this) }
113+
func (this ccret) U64() uint64 { return uint64(this) }
114+
func (this ccret) F32() float32 { return float32(this) }
115+
func (this ccret) F64() float64 { return float64(this) }
116+
func (this ccret) Ptr() unsafe.Pointer { return unsafe.Pointer(uintptr(this)) }
117+
func (this ccret) Uptr() uintptr { return uintptr(this) }
118+
func (this ccret) Bool() bool { return this != 0 }
119+
func (this ccret) Strc() string {
120+
// char* => string
121+
return qtrt.GoString(this.Ptr())
122+
}
123+
func (this ccret) Strq() string {
124+
// QString => string
125+
ba := this.Cobj().CC0(QStringToUtf8)
126+
rv := ba.Cobj().CC0(QByteArrayData)
127+
return rv.Strc()
128+
}
129+
func (this ccret) Cobj() CObject { return CObject(this) }
130+
131+
// for Qt multiple inherit
132+
func (this ccret) Cobj2() CObject {
133+
return CObject(this.Uptr() + unsafe.Sizeof(uintptr(0)))
134+
}
135+
136+
func convgoargs2c(cmo *cppmethod, args []interface{}) []interface{} {
137+
var argv []interface{}
138+
if len(args) != cmo.argc() {
139+
log.Printf("WARN argc not match want %d have %d when call %s.%s\n",
140+
cmo.argc(), len(args), cmo.cls, cmo.mth)
141+
}
142+
for idx, arg := range args {
143+
val := convgoarg2c(cmo, idx, arg)
144+
argv = append(argv, val)
145+
}
146+
// log.Println("argc/want", len(argv), cmo.argc(), ":", argv)
147+
return argv
148+
}
149+
150+
func convgoarg2c(cmo *cppmethod, idx int, argx interface{}) interface{} {
151+
var rv interface{} = argx
152+
153+
argty := reflect.TypeOf(argx)
154+
argval := reflect.ValueOf(argx)
155+
if false {
156+
log.Println(argty, argval)
157+
}
158+
159+
cppty := cmo.types[idx]
160+
if argty == nil {
161+
if argx == nil {
162+
rv = unsafe.Pointer(nil)
163+
return rv
164+
}
165+
}
166+
switch argty.Kind() {
167+
case reflect.Invalid:
168+
log.Println("TODO", cmo.cls, cmo.mth)
169+
case reflect.String:
170+
// which one? // => QString // => charptr
171+
tval := argx.(string)
172+
if cppty == "char *" {
173+
rv = unsafe.Pointer(nil)
174+
// val1 := C.CString(arg.(string))
175+
// val2 := unsafe.Pointer(val1)
176+
val1 := []byte(tval)
177+
if len(val1) > 0 {
178+
val2 := unsafe.Pointer(&val1[0]) // works
179+
rv = val2
180+
}
181+
} else if strings.HasPrefix(cppty, "QString") {
182+
val1 := CC0(QStringNew5, tval)
183+
rv = val1.Ptr()
184+
}
185+
case reflect.Slice:
186+
if argty.Elem().Kind() == reflect.String {
187+
rv = qtrt.StringSliceToCCharPP(argx.([]string))
188+
// log.Println("converted", argty, arg)
189+
}
190+
case reflect.Int:
191+
if cmo.argisref(idx) { // fix int&
192+
rvp := reflect.New(argty)
193+
rvp.Elem().Set(argval)
194+
rv = unsafe.Pointer(rvp.Pointer())
195+
}
196+
case reflect.Bool: // just ok
197+
case reflect.Uintptr:
198+
log.Println("wtt", idx, argx)
199+
case reflect.Struct:
200+
if argty == ccrety {
201+
arg := argx.(ccret)
202+
rv = arg.Ptr()
203+
}
204+
default:
205+
log.Println("wtt", idx, argty, argty.Kind(), argval)
206+
}
207+
208+
return rv
209+
}
210+
211+
type cppmethod struct {
212+
cls string
213+
mth string
214+
types []string
215+
names []string
216+
isconst bool
217+
}
218+
219+
func (this *cppmethod) isctor() bool {
220+
return this.cls != "" && (this.cls == this.mth)
221+
}
222+
223+
func (this *cppmethod) isdtor() bool {
224+
return strings.HasPrefix(this.mth, "~")
225+
}
226+
227+
func (this *cppmethod) ismth() bool {
228+
return this.cls != ""
229+
}
230+
231+
func (this *cppmethod) argc() int { return len(this.types) }
232+
func (this *cppmethod) argisref(idx int) bool {
233+
return strings.Count(this.types[idx], "&") == 1
234+
}
235+
func (this *cppmethod) argisptr(idx int) bool {
236+
return strings.Count(this.types[idx], "*") == 1
237+
}
238+
239+
func cppfilt(mgname string) *cppmethod {
240+
cmo := &cppmethod{}
241+
line, err := demangle.ToString(mgname)
242+
qtrt.ErrPrint(err)
243+
// log.Println(mgname, line)
244+
245+
{
246+
// src := []byte("cos(x) + 1i*sin(x) // Euler")
247+
src := []byte(line)
248+
249+
// Initialize the scanner.
250+
var s scanner.Scanner
251+
fset := token.NewFileSet() // positions are relative to fset
252+
file := fset.AddFile("", fset.Base(), len(src)) // register input "file"
253+
s.Init(file, src, nil /* no error handler */, scanner.ScanComments)
254+
255+
var idts []string
256+
var colon = 0
257+
// Repeated calls to Scan yield the token sequence found in the input.
258+
for {
259+
pos, tok, lit := s.Scan()
260+
if tok == token.EOF {
261+
break
262+
}
263+
// fmt.Printf("%s\t%s\t%q\n", fset.Position(pos), tok, lit)
264+
switch tok {
265+
case token.CONST:
266+
case token.IDENT:
267+
idts = append(idts, lit)
268+
case token.COLON:
269+
colon += 1
270+
if colon == 2 {
271+
cmo.cls = idts[len(idts)-1]
272+
}
273+
case token.LPAREN:
274+
cmo.mth = idts[len(idts)-1]
275+
idts = []string{}
276+
case token.RPAREN:
277+
if len(idts) == 0 {
278+
break
279+
}
280+
tyfld := strings.Join(idts, " ")
281+
cmo.types = append(cmo.types, tyfld)
282+
idts = []string{}
283+
case token.MUL:
284+
idts = append(idts, tok.String())
285+
case token.AND:
286+
idts = append(idts, tok.String())
287+
case token.COMMA:
288+
if len(idts) == 0 {
289+
break
290+
}
291+
tyfld := strings.Join(idts, " ")
292+
cmo.types = append(cmo.types, tyfld)
293+
idts = []string{}
294+
case token.SEMICOLON:
295+
case token.LSS: // TODO template<>
296+
idts = append(idts, tok.String())
297+
case token.GTR:
298+
idts = append(idts, tok.String())
299+
default:
300+
log.Println("wtt", fset.Position(pos), tok, lit, mgname)
301+
}
302+
}
303+
// log.Printf("%#v\n", cmo)
304+
}
305+
306+
return cmo
307+
}

0 commit comments

Comments
 (0)