Merge lp:~larryprice/ciborium/go1.6-port into lp:ciborium
- go1.6-port
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Stephen M. Webb | ||||
Approved revision: | 159 | ||||
Merged at revision: | 159 | ||||
Proposed branch: | lp:~larryprice/ciborium/go1.6-port | ||||
Merge into: | lp:ciborium | ||||
Diff against target: |
797 lines (+162/-110) 11 files modified
cmd/ciborium-ui/main.go (+9/-4) qml.v1/bridge.go (+63/-25) qml.v1/cpp/capi.cpp (+15/-15) qml.v1/cpp/capi.h (+20/-19) qml.v1/cpp/connector.h (+2/-2) qml.v1/cpp/govalue.cpp (+16/-16) qml.v1/cpp/govalue.h (+4/-4) qml.v1/cpp/govaluetype.cpp (+6/-6) qml.v1/cpp/govaluetype.h (+4/-4) qml.v1/datatype.go (+1/-2) qml.v1/qml.go (+22/-13) |
||||
To merge this branch: | bzr merge lp:~larryprice/ciborium/go1.6-port | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stephen M. Webb (community) | Approve | ||
Review via email: mp+297801@code.launchpad.net |
Commit message
Fix crash on startup hopefully related to bug #1592421.
Description of the change
Fix crash on startup hopefully related to bug #1592421.
As far as I can tell, this crash was happening due to a new cgo error that only happens in go1.6. My assumption is that the binary was compiled using go1.6. go-qml has related bug https:/
I also adjusted the syntax being used to run the application with go-qml to get better error reporting. With the old method, I saw a simple stacktrace with no useful information. With the new method, I was able to see: `panic: runtime error: cgo argument has Go pointer to Go pointer` which led me to this particular solution.
Preview Diff
1 | === modified file 'cmd/ciborium-ui/main.go' |
2 | --- cmd/ciborium-ui/main.go 2015-06-11 10:35:19 +0000 |
3 | +++ cmd/ciborium-ui/main.go 2016-06-17 18:52:58 +0000 |
4 | @@ -77,14 +77,18 @@ |
5 | // set default logger flags to get more useful info |
6 | log.SetFlags(log.LstdFlags | log.Lshortfile) |
7 | |
8 | - // not in qml.v1 |
9 | - //qml.Init(nil) |
10 | + err := qml.Run(run) |
11 | + if err != nil { |
12 | + log.Fatal(err) |
13 | + } |
14 | +} |
15 | + |
16 | +func run() error { |
17 | engine := qml.NewEngine() |
18 | component, err := engine.LoadFile(mainQmlPath) |
19 | if err != nil { |
20 | - log.Fatal(err) |
21 | + return err |
22 | } |
23 | - |
24 | context := engine.Context() |
25 | |
26 | driveCtrl, err := newDriveControl() |
27 | @@ -98,6 +102,7 @@ |
28 | |
29 | window.Show() |
30 | window.Wait() |
31 | + return nil |
32 | } |
33 | |
34 | func newDriveControl() (*driveControl, error) { |
35 | |
36 | === modified file 'qml.v1/bridge.go' |
37 | --- qml.v1/bridge.go 2015-06-11 10:25:43 +0000 |
38 | +++ qml.v1/bridge.go 2016-06-17 18:52:58 +0000 |
39 | @@ -203,6 +203,35 @@ |
40 | owner valueOwner |
41 | } |
42 | |
43 | +// cgoFolds holds all fold values that get reference to on the cgo space. |
44 | +// Since Go Pointer are not allowed to be held by cgo. We need a lookup |
45 | +// table to interface the two space. |
46 | +var cgoFolds = make(map[C.GoRef]*valueFold) |
47 | + |
48 | +// GoRef index the valueFold value and return a lookup |
49 | +// key (C.GoRef), so that we can retrieve the fold using |
50 | +// the C.GoRef. need to cross between go and cgo |
51 | +func (f *valueFold) goRef() C.GoRef { |
52 | + ref := C.GoRef(uintptr(unsafe.Pointer(f))) |
53 | + cgoFolds[ref] = f |
54 | + return ref |
55 | +} |
56 | + |
57 | +// destroyRef remove the valueFold reference from the lookup table. |
58 | +func (f *valueFold) destroyRef() { |
59 | + ref := C.GoRef(uintptr(unsafe.Pointer(f))) |
60 | + delete(cgoFolds, ref) |
61 | +} |
62 | + |
63 | +// getFoldFromGoRef return the valueFold value located at ref |
64 | +func getFoldFromGoRef(ref C.GoRef) *valueFold { |
65 | + fold := cgoFolds[ref] |
66 | + if fold == nil { |
67 | + panic("cannot find fold go reference") |
68 | + } |
69 | + return fold |
70 | +} |
71 | + |
72 | type valueOwner uint8 |
73 | |
74 | const ( |
75 | @@ -251,7 +280,7 @@ |
76 | gvalue: gvalue, |
77 | owner: owner, |
78 | } |
79 | - fold.cvalue = C.newGoValue(unsafe.Pointer(fold), typeInfo(gvalue), parent) |
80 | + fold.cvalue = C.newGoValue(fold.goRef(), typeInfo(gvalue), parent) |
81 | if prev != nil { |
82 | // Put new fold first so the single cppOwner, if any, is always the first entry. |
83 | fold.next = prev |
84 | @@ -289,29 +318,37 @@ |
85 | var typeNew = make(map[*valueFold]bool) |
86 | |
87 | //export hookGoValueTypeNew |
88 | -func hookGoValueTypeNew(cvalue unsafe.Pointer, specp unsafe.Pointer) (foldp unsafe.Pointer) { |
89 | +func hookGoValueTypeNew(cvalue unsafe.Pointer, specr C.GoTypeSpec_) (foldr C.GoRef) { |
90 | // Initialization is postponed until the engine is available, so that |
91 | // we can hand Init the qml.Object that represents the object. |
92 | - init := reflect.ValueOf((*TypeSpec)(specp).Init) |
93 | + spec := types[specr] |
94 | + if spec == nil { |
95 | + panic("cannot find the specified TypeSpec") |
96 | + } |
97 | + |
98 | + init := reflect.ValueOf(spec.Init) |
99 | fold := &valueFold{ |
100 | init: init, |
101 | gvalue: reflect.New(init.Type().In(0).Elem()).Interface(), |
102 | cvalue: cvalue, |
103 | owner: jsOwner, |
104 | } |
105 | + |
106 | typeNew[fold] = true |
107 | //fmt.Printf("[DEBUG] value alive (type-created): cvalue=%x gvalue=%x/%#v\n", fold.cvalue, addrOf(fold.gvalue), fold.gvalue) |
108 | stats.valuesAlive(+1) |
109 | - return unsafe.Pointer(fold) |
110 | + return fold.goRef() |
111 | } |
112 | |
113 | //export hookGoValueDestroyed |
114 | -func hookGoValueDestroyed(enginep unsafe.Pointer, foldp unsafe.Pointer) { |
115 | - fold := (*valueFold)(foldp) |
116 | +func hookGoValueDestroyed(enginep unsafe.Pointer, foldr C.GoRef) { |
117 | + fold := getFoldFromGoRef(foldr) |
118 | + |
119 | engine := fold.engine |
120 | if engine == nil { |
121 | before := len(typeNew) |
122 | delete(typeNew, fold) |
123 | + fold.destroyRef() |
124 | if len(typeNew) == before { |
125 | panic("destroying value without an associated engine; who created the value?") |
126 | } |
127 | @@ -342,6 +379,7 @@ |
128 | delete(engines, engine.addr) |
129 | } |
130 | } |
131 | + fold.destroyRef() |
132 | } |
133 | //fmt.Printf("[DEBUG] value destroyed: cvalue=%x gvalue=%x/%#v\n", fold.cvalue, addrOf(fold.gvalue), fold.gvalue) |
134 | stats.valuesAlive(-1) |
135 | @@ -360,8 +398,8 @@ |
136 | } |
137 | |
138 | //export hookGoValueReadField |
139 | -func hookGoValueReadField(enginep, foldp unsafe.Pointer, reflectIndex, getIndex, setIndex C.int, resultdv *C.DataValue) { |
140 | - fold := ensureEngine(enginep, foldp) |
141 | +func hookGoValueReadField(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex, getIndex, setIndex C.int, resultdv *C.DataValue) { |
142 | + fold := ensureEngine(enginep, foldr) |
143 | |
144 | var field reflect.Value |
145 | if getIndex >= 0 { |
146 | @@ -376,7 +414,7 @@ |
147 | // TODO Handle getters that return []qml.Object. |
148 | // TODO Handle other GoValue slices (!= []qml.Object). |
149 | resultdv.dataType = C.DTListProperty |
150 | - *(*unsafe.Pointer)(unsafe.Pointer(&resultdv.data)) = C.newListProperty(foldp, C.intptr_t(reflectIndex), C.intptr_t(setIndex)) |
151 | + *(*unsafe.Pointer)(unsafe.Pointer(&resultdv.data)) = C.newListProperty(C.GoRef(foldr), C.intptr_t(reflectIndex), C.intptr_t(setIndex)) |
152 | return |
153 | } |
154 | |
155 | @@ -406,8 +444,8 @@ |
156 | } |
157 | |
158 | //export hookGoValueWriteField |
159 | -func hookGoValueWriteField(enginep, foldp unsafe.Pointer, reflectIndex, setIndex C.int, assigndv *C.DataValue) { |
160 | - fold := ensureEngine(enginep, foldp) |
161 | +func hookGoValueWriteField(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex, setIndex C.int, assigndv *C.DataValue) { |
162 | + fold := ensureEngine(enginep, foldr) |
163 | v := reflect.ValueOf(fold.gvalue) |
164 | ve := v |
165 | for ve.Type().Kind() == reflect.Ptr { |
166 | @@ -483,8 +521,8 @@ |
167 | ) |
168 | |
169 | //export hookGoValueCallMethod |
170 | -func hookGoValueCallMethod(enginep, foldp unsafe.Pointer, reflectIndex C.int, args *C.DataValue) { |
171 | - fold := ensureEngine(enginep, foldp) |
172 | +func hookGoValueCallMethod(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex C.int, args *C.DataValue) { |
173 | + fold := ensureEngine(enginep, foldr) |
174 | v := reflect.ValueOf(fold.gvalue) |
175 | |
176 | // TODO Must assert that v is necessarily a pointer here, but we shouldn't have to manipulate |
177 | @@ -548,7 +586,7 @@ |
178 | } |
179 | |
180 | //export hookGoValuePaint |
181 | -func hookGoValuePaint(enginep, foldp unsafe.Pointer, reflectIndex C.intptr_t) { |
182 | +func hookGoValuePaint(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex C.intptr_t) { |
183 | // Besides a convenience this is a workaround for http://golang.org/issue/8588 |
184 | defer printPaintPanic() |
185 | defer atomic.StoreUintptr(&guiPaintRef, 0) |
186 | @@ -557,7 +595,7 @@ |
187 | // so no two paintings should be happening at the same time. |
188 | atomic.StoreUintptr(&guiPaintRef, cdata.Ref()) |
189 | |
190 | - fold := ensureEngine(enginep, foldp) |
191 | + fold := ensureEngine(enginep, foldr) |
192 | if fold.init.IsValid() { |
193 | return |
194 | } |
195 | @@ -568,8 +606,8 @@ |
196 | method.Call([]reflect.Value{reflect.ValueOf(painter)}) |
197 | } |
198 | |
199 | -func ensureEngine(enginep, foldp unsafe.Pointer) *valueFold { |
200 | - fold := (*valueFold)(foldp) |
201 | +func ensureEngine(enginep unsafe.Pointer, foldr C.GoRef) *valueFold { |
202 | + fold := getFoldFromGoRef(foldr) |
203 | if fold.engine != nil { |
204 | if fold.init.IsValid() { |
205 | initGoType(fold) |
206 | @@ -637,22 +675,22 @@ |
207 | } |
208 | |
209 | //export hookListPropertyAt |
210 | -func hookListPropertyAt(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t, index C.int) (objp unsafe.Pointer) { |
211 | - fold := (*valueFold)(foldp) |
212 | +func hookListPropertyAt(foldr C.GoRef, reflectIndex, setIndex C.intptr_t, index C.int) (objp unsafe.Pointer) { |
213 | + fold := getFoldFromGoRef(foldr) |
214 | slice := listSlice(fold, reflectIndex) |
215 | return (*slice)[int(index)].Common().addr |
216 | } |
217 | |
218 | //export hookListPropertyCount |
219 | -func hookListPropertyCount(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t) C.int { |
220 | - fold := (*valueFold)(foldp) |
221 | +func hookListPropertyCount(foldr C.GoRef, reflectIndex, setIndex C.intptr_t) C.int { |
222 | + fold := getFoldFromGoRef(foldr) |
223 | slice := listSlice(fold, reflectIndex) |
224 | return C.int(len(*slice)) |
225 | } |
226 | |
227 | //export hookListPropertyAppend |
228 | -func hookListPropertyAppend(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t, objp unsafe.Pointer) { |
229 | - fold := (*valueFold)(foldp) |
230 | +func hookListPropertyAppend(foldr C.GoRef, reflectIndex, setIndex C.intptr_t, objp unsafe.Pointer) { |
231 | + fold := getFoldFromGoRef(foldr) |
232 | slice := listSlice(fold, reflectIndex) |
233 | var objdv C.DataValue |
234 | objdv.dataType = C.DTObject |
235 | @@ -666,8 +704,8 @@ |
236 | } |
237 | |
238 | //export hookListPropertyClear |
239 | -func hookListPropertyClear(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t) { |
240 | - fold := (*valueFold)(foldp) |
241 | +func hookListPropertyClear(foldr C.GoRef, reflectIndex, setIndex C.intptr_t) { |
242 | + fold := getFoldFromGoRef(foldr) |
243 | slice := listSlice(fold, reflectIndex) |
244 | newslice := (*slice)[0:0] |
245 | if setIndex >= 0 { |
246 | |
247 | === modified file 'qml.v1/cpp/capi.cpp' |
248 | --- qml.v1/cpp/capi.cpp 2015-06-11 10:10:38 +0000 |
249 | +++ qml.v1/cpp/capi.cpp 2016-06-17 18:52:58 +0000 |
250 | @@ -492,7 +492,7 @@ |
251 | qobject->setParent(qparent); |
252 | } |
253 | |
254 | -error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, void *func, int argsLen) |
255 | +error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, GoRef func, int argsLen) |
256 | { |
257 | QObject *qobject = reinterpret_cast<QObject *>(object); |
258 | QQmlEngine *qengine = reinterpret_cast<QQmlEngine *>(engine); |
259 | @@ -543,17 +543,17 @@ |
260 | return dynamic_cast<QQuickView *>(qobject) ? 1 : 0; |
261 | } |
262 | |
263 | -error *objectGoAddr(QObject_ *object, GoAddr **addr) |
264 | +error *objectGoRef(QObject_ *object, GoRef *ref) |
265 | { |
266 | QObject *qobject = static_cast<QObject *>(object); |
267 | GoValue *goValue = dynamic_cast<GoValue *>(qobject); |
268 | if (goValue) { |
269 | - *addr = goValue->addr; |
270 | + *ref = goValue->ref; |
271 | return 0; |
272 | } |
273 | GoPaintedValue *goPaintedValue = dynamic_cast<GoPaintedValue *>(qobject); |
274 | if (goPaintedValue) { |
275 | - *addr = goPaintedValue->addr; |
276 | + *ref= goPaintedValue->ref; |
277 | return 0; |
278 | } |
279 | return errorf("QML object is not backed by a Go value"); |
280 | @@ -571,13 +571,13 @@ |
281 | delete reinterpret_cast<QString *>(s); |
282 | } |
283 | |
284 | -GoValue_ *newGoValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject_ *parent) |
285 | +GoValue_ *newGoValue(GoRef ref, GoTypeInfo *typeInfo, QObject_ *parent) |
286 | { |
287 | QObject *qparent = reinterpret_cast<QObject *>(parent); |
288 | if (typeInfo->paint) { |
289 | - return new GoPaintedValue(addr, typeInfo, qparent); |
290 | + return new GoPaintedValue(ref, typeInfo, qparent); |
291 | } |
292 | - return new GoValue(addr, typeInfo, qparent); |
293 | + return new GoValue(ref, typeInfo, qparent); |
294 | } |
295 | |
296 | void goValueActivate(GoValue_ *value, GoTypeInfo *typeInfo, int addrOffset) |
297 | @@ -749,13 +749,13 @@ |
298 | GoValue *goValue = dynamic_cast<GoValue *>(qobject); |
299 | if (goValue) { |
300 | value->dataType = DTGoAddr; |
301 | - *(void **)(value->data) = goValue->addr; |
302 | + *(uintptr_t*)(value->data) = goValue->ref; |
303 | break; |
304 | } |
305 | GoPaintedValue *goPaintedValue = dynamic_cast<GoPaintedValue *>(qobject); |
306 | if (goPaintedValue) { |
307 | value->dataType = DTGoAddr; |
308 | - *(void **)(value->data) = goPaintedValue->addr; |
309 | + *(uintptr_t*)(value->data) = goPaintedValue->ref; |
310 | break; |
311 | } |
312 | value->dataType = DTObject; |
313 | @@ -813,28 +813,28 @@ |
314 | |
315 | QObject *listPropertyAt(QQmlListProperty<QObject> *list, int i) |
316 | { |
317 | - return reinterpret_cast<QObject *>(hookListPropertyAt(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, i)); |
318 | + return reinterpret_cast<QObject *>(hookListPropertyAt((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, i)); |
319 | } |
320 | |
321 | int listPropertyCount(QQmlListProperty<QObject> *list) |
322 | { |
323 | - return hookListPropertyCount(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2); |
324 | + return hookListPropertyCount((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2); |
325 | } |
326 | |
327 | void listPropertyAppend(QQmlListProperty<QObject> *list, QObject *obj) |
328 | { |
329 | - hookListPropertyAppend(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, obj); |
330 | + hookListPropertyAppend((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, obj); |
331 | } |
332 | |
333 | void listPropertyClear(QQmlListProperty<QObject> *list) |
334 | { |
335 | - hookListPropertyClear(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2); |
336 | + hookListPropertyClear((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2); |
337 | } |
338 | |
339 | -QQmlListProperty_ *newListProperty(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex) |
340 | +QQmlListProperty_ *newListProperty(GoRef ref, intptr_t reflectIndex, intptr_t setIndex) |
341 | { |
342 | QQmlListProperty<QObject> *list = new QQmlListProperty<QObject>(); |
343 | - list->data = addr; |
344 | + list->data = (void*)ref; |
345 | list->dummy1 = (void*)reflectIndex; |
346 | list->dummy2 = (void*)setIndex; |
347 | list->at = listPropertyAt; |
348 | |
349 | === modified file 'qml.v1/cpp/capi.h' |
350 | --- qml.v1/cpp/capi.h 2015-06-11 10:10:38 +0000 |
351 | +++ qml.v1/cpp/capi.h 2016-06-17 18:52:58 +0000 |
352 | @@ -29,7 +29,8 @@ |
353 | typedef void QImage_; |
354 | typedef void GoValue_; |
355 | typedef void GoAddr; |
356 | -typedef void GoTypeSpec_; |
357 | +typedef uintptr_t GoRef; |
358 | +typedef uintptr_t GoTypeSpec_; |
359 | |
360 | typedef char error; |
361 | error *errorf(const char *format, ...); |
362 | @@ -140,8 +141,8 @@ |
363 | int objectIsComponent(QObject_ *object); |
364 | int objectIsWindow(QObject_ *object); |
365 | int objectIsView(QObject_ *object); |
366 | -error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, void *func, int argsLen); |
367 | -error *objectGoAddr(QObject_ *object, GoAddr **addr); |
368 | +error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, GoRef func, int argsLen); |
369 | +error *objectGoRef(QObject_ *object, GoRef *ref); |
370 | |
371 | QQmlComponent_ *newComponent(QQmlEngine_ *engine, QObject_ *parent); |
372 | void componentLoadURL(QQmlComponent_ *component, const char *url, int urlLen); |
373 | @@ -166,7 +167,7 @@ |
374 | QString_ *newString(const char *data, int len); |
375 | void delString(QString_ *s); |
376 | |
377 | -GoValue_ *newGoValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject_ *parent); |
378 | +GoValue_ *newGoValue(GoRef ref, GoTypeInfo *typeInfo, QObject_ *parent); |
379 | void goValueActivate(GoValue_ *value, GoTypeInfo *typeInfo, int addrOffset); |
380 | |
381 | void packDataValue(QVariant_ *var, DataValue *result); |
382 | @@ -174,30 +175,30 @@ |
383 | |
384 | QVariantList_ *newVariantList(DataValue *list, int len); |
385 | |
386 | -QQmlListProperty_ *newListProperty(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex); |
387 | +QQmlListProperty_ *newListProperty(GoRef ref, intptr_t reflectIndex, intptr_t setIndex); |
388 | |
389 | -int registerType(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ *spec); |
390 | -int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ *spec); |
391 | +int registerType(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ spec); |
392 | +int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ spec); |
393 | |
394 | void installLogHandler(); |
395 | |
396 | void hookIdleTimer(); |
397 | void hookLogHandler(LogMessage *message); |
398 | -void hookGoValueReadField(QQmlEngine_ *engine, GoAddr *addr, int memberIndex, int getIndex, int setIndex, DataValue *result); |
399 | -void hookGoValueWriteField(QQmlEngine_ *engine, GoAddr *addr, int memberIndex, int setIndex, DataValue *assign); |
400 | -void hookGoValueCallMethod(QQmlEngine_ *engine, GoAddr *addr, int memberIndex, DataValue *result); |
401 | -void hookGoValueDestroyed(QQmlEngine_ *engine, GoAddr *addr); |
402 | -void hookGoValuePaint(QQmlEngine_ *engine, GoAddr *addr, intptr_t reflextIndex); |
403 | +void hookGoValueReadField(QQmlEngine_ *engine, GoRef ref, int memberIndex, int getIndex, int setIndex, DataValue *result); |
404 | +void hookGoValueWriteField(QQmlEngine_ *engine, GoRef ref, int memberIndex, int setIndex, DataValue *assign); |
405 | +void hookGoValueCallMethod(QQmlEngine_ *engine, GoRef ref, int memberIndex, DataValue *result); |
406 | +void hookGoValueDestroyed(QQmlEngine_ *engine, GoRef ref); |
407 | +void hookGoValuePaint(QQmlEngine_ *engine, GoRef ref, intptr_t reflextIndex); |
408 | QImage_ *hookRequestImage(void *imageFunc, char *id, int idLen, int width, int height); |
409 | -GoAddr *hookGoValueTypeNew(GoValue_ *value, GoTypeSpec_ *spec); |
410 | +GoRef hookGoValueTypeNew(GoValue_ *value, GoTypeSpec_ spec); |
411 | void hookWindowHidden(QObject_ *addr); |
412 | -void hookSignalCall(QQmlEngine_ *engine, void *func, DataValue *params); |
413 | -void hookSignalDisconnect(void *func); |
414 | +void hookSignalCall(QQmlEngine_ *engine, GoRef func, DataValue *params); |
415 | +void hookSignalDisconnect(GoRef func); |
416 | void hookPanic(char *message); |
417 | -int hookListPropertyCount(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex); |
418 | -QObject_ *hookListPropertyAt(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex, int i); |
419 | -void hookListPropertyAppend(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex, QObject_ *obj); |
420 | -void hookListPropertyClear(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex); |
421 | +int hookListPropertyCount(GoRef ref, intptr_t reflectIndex, intptr_t setIndex); |
422 | +QObject_ *hookListPropertyAt(GoRef ref, intptr_t reflectIndex, intptr_t setIndex, int i); |
423 | +void hookListPropertyAppend(GoRef ref, intptr_t reflectIndex, intptr_t setIndex, QObject_ *obj); |
424 | +void hookListPropertyClear(GoRef ref, intptr_t reflectIndex, intptr_t setIndex); |
425 | |
426 | void registerResourceData(int version, char *tree, char *name, char *data); |
427 | void unregisterResourceData(int version, char *tree, char *name, char *data); |
428 | |
429 | === modified file 'qml.v1/cpp/connector.h' |
430 | --- qml.v1/cpp/connector.h 2015-06-11 10:10:38 +0000 |
431 | +++ qml.v1/cpp/connector.h 2016-06-17 18:52:58 +0000 |
432 | @@ -11,7 +11,7 @@ |
433 | |
434 | public: |
435 | |
436 | - Connector(QObject *sender, QMetaMethod method, QQmlEngine *engine, void *func, int argsLen) |
437 | + Connector(QObject *sender, QMetaMethod method, QQmlEngine *engine, GoRef func, int argsLen) |
438 | : QObject(sender), engine(engine), method(method), func(func), argsLen(argsLen) {}; |
439 | |
440 | virtual ~Connector(); |
441 | @@ -27,7 +27,7 @@ |
442 | |
443 | QQmlEngine *engine; |
444 | QMetaMethod method; |
445 | - void *func; |
446 | + GoRef func; |
447 | int argsLen; |
448 | }; |
449 | |
450 | |
451 | === modified file 'qml.v1/cpp/govalue.cpp' |
452 | --- qml.v1/cpp/govalue.cpp 2015-06-11 10:10:38 +0000 |
453 | +++ qml.v1/cpp/govalue.cpp 2016-06-17 18:52:58 +0000 |
454 | @@ -13,7 +13,7 @@ |
455 | class GoValueMetaObject : public QAbstractDynamicMetaObject |
456 | { |
457 | public: |
458 | - GoValueMetaObject(QObject* value, GoAddr *addr, GoTypeInfo *typeInfo); |
459 | + GoValueMetaObject(QObject* value, GoRef ref, GoTypeInfo *typeInfo); |
460 | |
461 | void activatePropIndex(int propIndex); |
462 | |
463 | @@ -22,12 +22,12 @@ |
464 | |
465 | private: |
466 | QObject *value; |
467 | - GoAddr *addr; |
468 | + GoRef ref; |
469 | GoTypeInfo *typeInfo; |
470 | }; |
471 | |
472 | -GoValueMetaObject::GoValueMetaObject(QObject *value, GoAddr *addr, GoTypeInfo *typeInfo) |
473 | - : value(value), addr(addr), typeInfo(typeInfo) |
474 | +GoValueMetaObject::GoValueMetaObject(QObject *value, GoRef ref, GoTypeInfo *typeInfo) |
475 | + : value(value), ref(ref), typeInfo(typeInfo) |
476 | { |
477 | //d->parent = static_cast<QAbstractDynamicMetaObject *>(priv->metaObject); |
478 | *static_cast<QMetaObject *>(this) = *metaObjectFor(typeInfo); |
479 | @@ -53,7 +53,7 @@ |
480 | if (memberInfo->metaIndex == idx) { |
481 | if (c == QMetaObject::ReadProperty) { |
482 | DataValue result; |
483 | - hookGoValueReadField(qmlEngine(value), addr, memberInfo->reflectIndex, memberInfo->reflectGetIndex, memberInfo->reflectSetIndex, &result); |
484 | + hookGoValueReadField(qmlEngine(value), ref, memberInfo->reflectIndex, memberInfo->reflectGetIndex, memberInfo->reflectSetIndex, &result); |
485 | if (memberInfo->memberType == DTListProperty) { |
486 | if (result.dataType != DTListProperty) { |
487 | panicf("reading DTListProperty field returned non-DTListProperty result"); |
488 | @@ -71,7 +71,7 @@ |
489 | DataValue assign; |
490 | QVariant *in = reinterpret_cast<QVariant *>(a[0]); |
491 | packDataValue(in, &assign); |
492 | - hookGoValueWriteField(qmlEngine(value), addr, memberInfo->reflectIndex, memberInfo->reflectSetIndex, &assign); |
493 | + hookGoValueWriteField(qmlEngine(value), ref, memberInfo->reflectIndex, memberInfo->reflectSetIndex, &assign); |
494 | activate(value, methodOffset() + (idx - propOffset), 0); |
495 | } |
496 | return -1; |
497 | @@ -95,7 +95,7 @@ |
498 | for (int i = 1; i < memberInfo->numIn+1; i++) { |
499 | packDataValue(reinterpret_cast<QVariant *>(a[i]), &args[i]); |
500 | } |
501 | - hookGoValueCallMethod(qmlEngine(value), addr, memberInfo->reflectIndex, args); |
502 | + hookGoValueCallMethod(qmlEngine(value), ref, memberInfo->reflectIndex, args); |
503 | if (memberInfo->numOut > 0) { |
504 | unpackDataValue(&args[0], reinterpret_cast<QVariant *>(a[0])); |
505 | } |
506 | @@ -121,16 +121,16 @@ |
507 | activate(value, methodOffset() + relativeIndex, 0); |
508 | } |
509 | |
510 | -GoValue::GoValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject *parent) |
511 | - : addr(addr), typeInfo(typeInfo) |
512 | +GoValue::GoValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent) |
513 | + : ref(ref), typeInfo(typeInfo) |
514 | { |
515 | - valueMeta = new GoValueMetaObject(this, addr, typeInfo); |
516 | + valueMeta = new GoValueMetaObject(this, ref, typeInfo); |
517 | setParent(parent); |
518 | } |
519 | |
520 | GoValue::~GoValue() |
521 | { |
522 | - hookGoValueDestroyed(qmlEngine(this), addr); |
523 | + hookGoValueDestroyed(qmlEngine(this), ref); |
524 | } |
525 | |
526 | void GoValue::activate(int propIndex) |
527 | @@ -138,10 +138,10 @@ |
528 | valueMeta->activatePropIndex(propIndex); |
529 | } |
530 | |
531 | -GoPaintedValue::GoPaintedValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject *parent) |
532 | - : addr(addr), typeInfo(typeInfo) |
533 | +GoPaintedValue::GoPaintedValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent) |
534 | + : ref(ref), typeInfo(typeInfo) |
535 | { |
536 | - valueMeta = new GoValueMetaObject(this, addr, typeInfo); |
537 | + valueMeta = new GoValueMetaObject(this, ref, typeInfo); |
538 | setParent(parent); |
539 | |
540 | QQuickItem::setFlag(QQuickItem::ItemHasContents, true); |
541 | @@ -150,7 +150,7 @@ |
542 | |
543 | GoPaintedValue::~GoPaintedValue() |
544 | { |
545 | - hookGoValueDestroyed(qmlEngine(this), addr); |
546 | + hookGoValueDestroyed(qmlEngine(this), ref); |
547 | } |
548 | |
549 | void GoPaintedValue::activate(int propIndex) |
550 | @@ -161,7 +161,7 @@ |
551 | void GoPaintedValue::paint(QPainter *painter) |
552 | { |
553 | painter->beginNativePainting(); |
554 | - hookGoValuePaint(qmlEngine(this), addr, typeInfo->paint->reflectIndex); |
555 | + hookGoValuePaint(qmlEngine(this), ref, typeInfo->paint->reflectIndex); |
556 | painter->endNativePainting(); |
557 | } |
558 | |
559 | |
560 | === modified file 'qml.v1/cpp/govalue.h' |
561 | --- qml.v1/cpp/govalue.h 2015-06-11 10:10:38 +0000 |
562 | +++ qml.v1/cpp/govalue.h 2016-06-17 18:52:58 +0000 |
563 | @@ -20,10 +20,10 @@ |
564 | Q_OBJECT |
565 | |
566 | public: |
567 | - GoAddr *addr; |
568 | + GoRef ref; |
569 | GoTypeInfo *typeInfo; |
570 | |
571 | - GoValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject *parent); |
572 | + GoValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent); |
573 | virtual ~GoValue(); |
574 | |
575 | void activate(int propIndex); |
576 | @@ -37,10 +37,10 @@ |
577 | Q_OBJECT |
578 | |
579 | public: |
580 | - GoAddr *addr; |
581 | + GoRef ref; |
582 | GoTypeInfo *typeInfo; |
583 | |
584 | - GoPaintedValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject *parent); |
585 | + GoPaintedValue(GoRef ref, GoTypeInfo *typeInfo, QObject *parent); |
586 | virtual ~GoPaintedValue(); |
587 | |
588 | void activate(int propIndex); |
589 | |
590 | === modified file 'qml.v1/cpp/govaluetype.cpp' |
591 | --- qml.v1/cpp/govaluetype.cpp 2015-06-11 10:10:38 +0000 |
592 | +++ qml.v1/cpp/govaluetype.cpp 2016-06-17 18:52:58 +0000 |
593 | @@ -3,12 +3,12 @@ |
594 | #define DEFINE_GOVALUETYPE(N) \ |
595 | template<> QMetaObject GoValueType<N>::staticMetaObject = QMetaObject(); \ |
596 | template<> GoTypeInfo *GoValueType<N>::typeInfo = 0; \ |
597 | - template<> GoTypeSpec_ *GoValueType<N>::typeSpec = 0; |
598 | + template<> GoTypeSpec_ GoValueType<N>::typeSpec = 0; |
599 | |
600 | #define DEFINE_GOPAINTEDVALUETYPE(N) \ |
601 | template<> QMetaObject GoPaintedValueType<N>::staticMetaObject = QMetaObject(); \ |
602 | template<> GoTypeInfo *GoPaintedValueType<N>::typeInfo = 0; \ |
603 | - template<> GoTypeSpec_ *GoPaintedValueType<N>::typeSpec = 0; |
604 | + template<> GoTypeSpec_ GoPaintedValueType<N>::typeSpec = 0; |
605 | |
606 | DEFINE_GOVALUETYPE(1) |
607 | DEFINE_GOVALUETYPE(2) |
608 | @@ -76,7 +76,7 @@ |
609 | static int goPaintedValueTypeN = 0; |
610 | |
611 | template<int N> |
612 | -int registerSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec) { |
613 | +int registerSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) { |
614 | GoValueType<N>::init(info, spec); |
615 | return qmlRegisterSingletonType< GoValueType<N> >(location, major, minor, name, [](QQmlEngine *qmlEngine, QJSEngine *jsEngine) -> QObject* { |
616 | QObject *singleton = new GoValueType<N>(); |
617 | @@ -86,7 +86,7 @@ |
618 | } |
619 | |
620 | template<int N> |
621 | -int registerPaintedSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec) { |
622 | +int registerPaintedSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) { |
623 | GoPaintedValueType<N>::init(info, spec); |
624 | return qmlRegisterSingletonType< GoPaintedValueType<N> >(location, major, minor, name, [](QQmlEngine *qmlEngine, QJSEngine *jsEngine) -> QObject* { |
625 | QObject *singleton = new GoPaintedValueType<N>(); |
626 | @@ -100,7 +100,7 @@ |
627 | #define GOPAINTEDVALUETYPE_CASE_SINGLETON(N) \ |
628 | case N: return registerPaintedSingletonN<N>(location, major, minor, name, info, spec); |
629 | |
630 | -int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec) |
631 | +int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) |
632 | { |
633 | if (!info->paint) { |
634 | switch (++goValueTypeN) { |
635 | @@ -178,7 +178,7 @@ |
636 | #define GOPAINTEDVALUETYPE_CASE(N) \ |
637 | case N: GoPaintedValueType<N>::init(info, spec); return qmlRegisterType< GoPaintedValueType<N> >(location, major, minor, name); |
638 | |
639 | -int registerType(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec) |
640 | +int registerType(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) |
641 | { |
642 | if (!info->paint) { |
643 | switch (++goValueTypeN) { |
644 | |
645 | === modified file 'qml.v1/cpp/govaluetype.h' |
646 | --- qml.v1/cpp/govaluetype.h 2015-06-11 10:10:38 +0000 |
647 | +++ qml.v1/cpp/govaluetype.h 2016-06-17 18:52:58 +0000 |
648 | @@ -11,14 +11,14 @@ |
649 | GoValueType() |
650 | : GoValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {}; |
651 | |
652 | - static void init(GoTypeInfo *info, GoTypeSpec_ *spec) |
653 | + static void init(GoTypeInfo *info, GoTypeSpec_ spec) |
654 | { |
655 | typeInfo = info; |
656 | typeSpec = spec; |
657 | static_cast<QMetaObject &>(staticMetaObject) = *metaObjectFor(typeInfo); |
658 | }; |
659 | |
660 | - static GoTypeSpec_ *typeSpec; |
661 | + static GoTypeSpec_ typeSpec; |
662 | static GoTypeInfo *typeInfo; |
663 | static QMetaObject staticMetaObject; |
664 | }; |
665 | @@ -31,14 +31,14 @@ |
666 | GoPaintedValueType() |
667 | : GoPaintedValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {}; |
668 | |
669 | - static void init(GoTypeInfo *info, GoTypeSpec_ *spec) |
670 | + static void init(GoTypeInfo *info, GoTypeSpec_ spec) |
671 | { |
672 | typeInfo = info; |
673 | typeSpec = spec; |
674 | static_cast<QMetaObject &>(staticMetaObject) = *metaObjectFor(typeInfo); |
675 | }; |
676 | |
677 | - static GoTypeSpec_ *typeSpec; |
678 | + static GoTypeSpec_ typeSpec; |
679 | static GoTypeInfo *typeInfo; |
680 | static QMetaObject staticMetaObject; |
681 | }; |
682 | |
683 | === modified file 'qml.v1/datatype.go' |
684 | --- qml.v1/datatype.go 2015-06-11 10:10:38 +0000 |
685 | +++ qml.v1/datatype.go 2016-06-17 18:52:58 +0000 |
686 | @@ -155,8 +155,7 @@ |
687 | case C.DTGoAddr: |
688 | // ObjectByName also does this fold conversion, to have access |
689 | // to the cvalue. Perhaps the fold should be returned. |
690 | - fold := (*(**valueFold)(datap)) |
691 | - ensureEngine(engine.addr, unsafe.Pointer(fold)) |
692 | + fold := ensureEngine(engine.addr, C.GoRef(uintptr(datap))) |
693 | return fold.gvalue |
694 | case C.DTInvalid: |
695 | return nil |
696 | |
697 | === modified file 'qml.v1/qml.go' |
698 | --- qml.v1/qml.go 2015-06-11 10:25:43 +0000 |
699 | +++ qml.v1/qml.go 2016-06-17 18:52:58 +0000 |
700 | @@ -484,8 +484,9 @@ |
701 | var result interface{} |
702 | var cerr *C.error |
703 | RunMain(func() { |
704 | - var fold *valueFold |
705 | - if cerr = C.objectGoAddr(obj.addr, (*unsafe.Pointer)(unsafe.Pointer(&fold))); cerr == nil { |
706 | + var foldr C.GoRef |
707 | + if cerr = C.objectGoRef(obj.addr, &foldr); cerr == nil { |
708 | + fold := getFoldFromGoRef(foldr) |
709 | result = fold.gvalue |
710 | } |
711 | }) |
712 | @@ -765,7 +766,7 @@ |
713 | }) |
714 | } |
715 | |
716 | -var connectedFunction = make(map[*interface{}]bool) |
717 | +var connectedFunction = make(map[C.GoRef]interface{}) |
718 | |
719 | // On connects the named signal from obj with the provided function, so that |
720 | // when obj next emits that signal, the function is called with the parameters |
721 | @@ -799,9 +800,10 @@ |
722 | csignal, csignallen := unsafeStringData(signal) |
723 | var cerr *C.error |
724 | RunMain(func() { |
725 | - cerr = C.objectConnect(obj.addr, csignal, csignallen, obj.engine.addr, unsafe.Pointer(&function), C.int(funcv.Type().NumIn())) |
726 | + funcr := C.GoRef(uintptr(unsafe.Pointer(&function))) |
727 | + cerr = C.objectConnect(obj.addr, csignal, csignallen, obj.engine.addr, funcr, C.int(funcv.Type().NumIn())) |
728 | if cerr == nil { |
729 | - connectedFunction[&function] = true |
730 | + connectedFunction[funcr] = function |
731 | stats.connectionsAlive(+1) |
732 | } |
733 | }) |
734 | @@ -809,9 +811,9 @@ |
735 | } |
736 | |
737 | //export hookSignalDisconnect |
738 | -func hookSignalDisconnect(funcp unsafe.Pointer) { |
739 | +func hookSignalDisconnect(funcr C.GoRef) { |
740 | before := len(connectedFunction) |
741 | - delete(connectedFunction, (*interface{})(funcp)) |
742 | + delete(connectedFunction, funcr) |
743 | if before == len(connectedFunction) { |
744 | panic("disconnecting unknown signal function") |
745 | } |
746 | @@ -819,12 +821,18 @@ |
747 | } |
748 | |
749 | //export hookSignalCall |
750 | -func hookSignalCall(enginep unsafe.Pointer, funcp unsafe.Pointer, args *C.DataValue) { |
751 | +func hookSignalCall(enginep unsafe.Pointer, funcr C.GoRef, args *C.DataValue) { |
752 | engine := engines[enginep] |
753 | if engine == nil { |
754 | panic("signal called after engine was destroyed") |
755 | } |
756 | - funcv := reflect.ValueOf(*(*interface{})(funcp)) |
757 | + |
758 | + function := connectedFunction[funcr] |
759 | + if function == nil { |
760 | + panic("signal called on disconnected function") |
761 | + } |
762 | + |
763 | + funcv := reflect.ValueOf(&function) |
764 | funct := funcv.Type() |
765 | numIn := funct.NumIn() |
766 | var params [C.MaxParams]reflect.Value |
767 | @@ -990,7 +998,7 @@ |
768 | private struct{} // Force use of fields by name. |
769 | } |
770 | |
771 | -var types []*TypeSpec |
772 | +var types = make(map[C.GoTypeSpec_]*TypeSpec) |
773 | |
774 | // RegisterTypes registers the provided list of type specifications for use |
775 | // by QML code. To access the registered types, they must be imported from the |
776 | @@ -1046,10 +1054,11 @@ |
777 | cloc := C.CString(location) |
778 | cname := C.CString(localSpec.Name) |
779 | cres := C.int(0) |
780 | + localSpecRef := C.GoTypeSpec_(uintptr(unsafe.Pointer(&localSpec))) |
781 | if localSpec.Singleton { |
782 | - cres = C.registerSingleton(cloc, C.int(major), C.int(minor), cname, customType, unsafe.Pointer(&localSpec)) |
783 | + cres = C.registerSingleton(cloc, C.int(major), C.int(minor), cname, customType, localSpecRef) |
784 | } else { |
785 | - cres = C.registerType(cloc, C.int(major), C.int(minor), cname, customType, unsafe.Pointer(&localSpec)) |
786 | + cres = C.registerType(cloc, C.int(major), C.int(minor), cname, customType, localSpecRef) |
787 | } |
788 | // It doesn't look like it keeps references to these, but it's undocumented and unclear. |
789 | C.free(unsafe.Pointer(cloc)) |
790 | @@ -1057,7 +1066,7 @@ |
791 | if cres == -1 { |
792 | err = fmt.Errorf("QML engine failed to register type; invalid type location or name?") |
793 | } else { |
794 | - types = append(types, &localSpec) |
795 | + types[localSpecRef] = &localSpec |
796 | } |
797 | }) |
798 |
Seems to fix the crash. Tested on m10.