[Kde-bindings] [Qyoto] crash when using QList returned by QMimeData.Urls
David Lechner
david at lechnology.com
Wed Feb 20 23:29:52 UTC 2013
On 2/20/2013 3:32 PM, Dimitar Dobrev wrote:
>
> Thank you. However, there is one last detail - could you make sure
> it works with the GetInstance call.
Added it back in and it works.
> The thing is that GetInstance retrieves a pointer from a mapping
> between managed objects and their unmanaged counterparts. This mapping
> guarantees that if you called, say, QTableView.SelectionModel twice,
> you'd get the same managed object. So you can see that calls to
> GetInstance cannot be simply ignored.
I was thinking that since this is a "value" list that we would always
pass a copy because these special type objects are treated more like
values (like int) than an object. I suppose that this may not be desired
in some cases though.
The attachment is a comprehensive patch that includes all of my changes.
-------------- next part --------------
>From 12a155ca21bc8f3332cf48ff9568c6ee40287eb2 Mon Sep 17 00:00:00 2001
From: David Lechner <david at lechnology.com>
Date: Wed, 20 Feb 2013 00:20:39 -0600
Subject: [PATCH 1/2] fixes marshalling QList<QUrl> (and others)
partial revert of commit ee40867bc873dcd0fd2e98be3fed37f754443ae0
---
assemblies/qyoto-qtcore/native/handlers.cpp | 22 +++---
assemblies/qyoto-qtcore/native/marshall_macros.h | 85 ++++++++++++++++++++++
assemblies/qyoto-qtgui/native/handlers.cpp | 12 +--
3 files changed, 102 insertions(+), 17 deletions(-)
diff --git a/assemblies/qyoto-qtcore/native/handlers.cpp b/assemblies/qyoto-qtcore/native/handlers.cpp
index 3f0f2f2..1a75879 100644
--- a/assemblies/qyoto-qtcore/native/handlers.cpp
+++ b/assemblies/qyoto-qtcore/native/handlers.cpp
@@ -1675,18 +1675,18 @@ void marshall_QListConstCharP(Marshall *m) {
DEF_LIST_MARSHALLER( QObjectList, QList<QObject*>, QObject )
-DEF_LIST_MARSHALLER( QByteArrayList, QList<QByteArray*>, QByteArray )
-DEF_LIST_MARSHALLER( QFileInfoList, QList<QFileInfo*>, QFileInfo )
-DEF_LIST_MARSHALLER( QLineFVector, QVector<QLineF*>, QLineF )
-DEF_LIST_MARSHALLER( QLineVector, QVector<QLine*>, QLine )
-DEF_LIST_MARSHALLER( QPointFVector, QVector<QPointF*>, QPointF )
-DEF_LIST_MARSHALLER( QPointVector, QVector<QPoint*>, QPoint )
+DEF_VALUELIST_MARSHALLER( QByteArrayList, QList<QByteArray>, QByteArray )
+DEF_VALUELIST_MARSHALLER( QFileInfoList, QFileInfoList, QFileInfo )
+DEF_VALUELIST_MARSHALLER( QLineFVector, QVector<QLineF>, QLineF )
+DEF_VALUELIST_MARSHALLER( QLineVector, QVector<QLine>, QLine )
+DEF_VALUELIST_MARSHALLER( QPointFVector, QVector<QPointF>, QPointF )
+DEF_VALUELIST_MARSHALLER( QPointVector, QVector<QPoint>, QPoint )
DEF_LIST_MARSHALLER( QRectFList, QList<QRectF*>, QRectF )
-DEF_LIST_MARSHALLER( QRectFVector, QVector<QRectF*>, QRectF )
-DEF_LIST_MARSHALLER( QRectVector, QVector<QRect*>, QRect )
-DEF_LIST_MARSHALLER( QUrlList, QList<QUrl*>, QUrl )
-DEF_LIST_MARSHALLER( QVariantList, QList<QVariant*>, QVariant )
-DEF_LIST_MARSHALLER( QVariantVector, QVector<QVariant*>, QVariant )
+DEF_VALUELIST_MARSHALLER( QRectFVector, QVector<QRectF>, QRectF )
+DEF_VALUELIST_MARSHALLER( QRectVector, QVector<QRect>, QRect )
+DEF_VALUELIST_MARSHALLER( QUrlList, QList<QUrl>, QUrl )
+DEF_VALUELIST_MARSHALLER( QVariantList, QList<QVariant>, QVariant )
+DEF_VALUELIST_MARSHALLER( QVariantVector, QVector<QVariant>, QVariant )
Q_DECL_EXPORT TypeHandler Qyoto_handlers[] = {
{ "bool*", marshall_boolR },
diff --git a/assemblies/qyoto-qtcore/native/marshall_macros.h b/assemblies/qyoto-qtcore/native/marshall_macros.h
index f1608ad..ba6b932 100644
--- a/assemblies/qyoto-qtcore/native/marshall_macros.h
+++ b/assemblies/qyoto-qtcore/native/marshall_macros.h
@@ -104,6 +104,91 @@ void marshall_ItemList(Marshall *m) {
#define DEF_LIST_MARSHALLER(ListIdent,ItemList,Item) namespace { char ListIdent##STR[] = #Item; } \
Marshall::HandlerFn marshall_##ListIdent = marshall_ItemList<Item,ItemList,ListIdent##STR>;
+template <class Item, class ItemList, const char *ItemSTR >
+void marshall_ValueListItem(Marshall *m) {
+ switch(m->action()) {
+ case Marshall::FromObject:
+ {
+ if (m->var().s_class == 0) {
+ m->item().s_class = 0;
+ return;
+ }
+ ItemList *cpplist = new ItemList;
+ QList<void*>* list = (QList<void*>*) (*ListToPointerList)(m->var().s_voidp);
+
+ for (int i = 0; i < list->size(); ++i) {
+ void* obj = list->at(i);
+ smokeqyoto_object * o = (smokeqyoto_object*) (*GetSmokeObject)(obj);
+
+ void* ptr = o->ptr;
+ ptr = o->smoke->cast(
+ ptr, // pointer
+ o->classId, // from
+ o->smoke->idClass(ItemSTR).index // to
+ );
+
+ cpplist->append(*(Item*) ptr);
+ (*FreeGCHandle)(obj);
+ }
+
+ m->item().s_voidp = cpplist;
+ m->next();
+
+ delete list;
+ (*FreeGCHandle)(m->var().s_voidp);
+
+ if (m->cleanup()) {
+ delete cpplist;
+ }
+ }
+ break;
+
+ case Marshall::ToObject:
+ {
+ ItemList *valuelist = (ItemList*)m->item().s_voidp;
+ if (valuelist == 0) {
+ m->var().s_voidp = 0;
+ break;
+ }
+
+ Smoke::ModuleIndex ix = m->smoke()->findClass(ItemSTR);
+ const char * className = qyoto_modules[ix.smoke].binding->className(ix.index);
+
+ void * al = (*ConstructList)(className);
+
+ for (int i=0; i < valuelist->size() ; ++i) {
+ void *p = (void *) &(valuelist->at(i));
+ void * obj = (*GetInstance)(p, true);
+
+ if (obj == 0) {
+ smokeqyoto_object * o = alloc_smokeqyoto_object(false, ix.smoke, ix.index, p);
+ obj = (*CreateInstance)(qyoto_resolve_classname(o), o);
+ }
+
+ (*AddIntPtrToList)(al, obj);
+ (*FreeGCHandle)(obj);
+ }
+
+ m->var().s_voidp = al;
+ m->next();
+
+ if (m->type().isStack()) {
+ delete valuelist;
+ }
+
+
+ }
+ break;
+
+ default:
+ m->unsupported();
+ break;
+ }
+}
+
+#define DEF_VALUELIST_MARSHALLER(ListIdent,ItemList,Item) namespace { char ListIdent##STR[] = #Item; } \
+ Marshall::HandlerFn marshall_##ListIdent = marshall_ValueListItem<Item,ItemList,ListIdent##STR>;
+
template <class Item1, class Item2, const char *Item1STR, const char *Item2STR,
const char *Item1CliSTR, const char *Item2CliSTR >
void marshall_QPair(Marshall *m) {
diff --git a/assemblies/qyoto-qtgui/native/handlers.cpp b/assemblies/qyoto-qtgui/native/handlers.cpp
index 884b556..46f15f9 100644
--- a/assemblies/qyoto-qtgui/native/handlers.cpp
+++ b/assemblies/qyoto-qtgui/native/handlers.cpp
@@ -274,17 +274,17 @@ DEF_LIST_MARSHALLER( QUndoStackList, QList<QUndoStack*>, QUndoStack )
DEF_LIST_MARSHALLER( QMdiSubWindowList, QList<QMdiSubWindow*>, QMdiSubWindow )
#endif
-DEF_LIST_MARSHALLER( QColorVector, QVector<QColor*>, QColor )
+DEF_VALUELIST_MARSHALLER( QColorVector, QVector<QColor>, QColor )
DEF_LIST_MARSHALLER( QImageTextKeyLangList, QList<QImageTextKeyLang*>, QImageTextKeyLang )
-DEF_LIST_MARSHALLER( QKeySequenceList, QList<QKeySequence*>, QKeySequence )
+DEF_VALUELIST_MARSHALLER( QKeySequenceList, QList<QKeySequence>, QKeySequence )
DEF_LIST_MARSHALLER( QModelIndexList, QList<QModelIndex*>, QModelIndex )
-DEF_LIST_MARSHALLER( QPixmapList, QList<QPixmap*>, QPixmap )
-DEF_LIST_MARSHALLER( QPolygonFList, QList<QPolygonF*>, QPolygonF )
+DEF_VALUELIST_MARSHALLER( QPixmapList, QList<QPixmap>, QPixmap )
+DEF_VALUELIST_MARSHALLER( QPolygonFList, QList<QPolygonF>, QPolygonF )
DEF_LIST_MARSHALLER( QTableWidgetSelectionRangeList, QList<QTableWidgetSelectionRange*>, QTableWidgetSelectionRange )
DEF_LIST_MARSHALLER( QTextBlockList, QList<QTextBlock*>, QTextBlock )
-DEF_LIST_MARSHALLER( QTextFormatVector, QVector<QTextFormat*>, QTextFormat )
+DEF_VALUELIST_MARSHALLER( QTextFormatVector, QVector<QTextFormat>, QTextFormat )
DEF_LIST_MARSHALLER( QTextLayoutFormatRangeList, QList<QTextLayout::FormatRange*>, QTextLayout::FormatRange)
-DEF_LIST_MARSHALLER( QTextLengthVector, QVector<QTextLength*>, QTextLength )
+DEF_VALUELIST_MARSHALLER( QTextLengthVector, QVector<QTextLength>, QTextLength )
#if QT_VERSION >= 0x40400
DEF_LIST_MARSHALLER( QPrinterInfoList, QList<QPrinterInfo*>, QPrinterInfo )
--
1.7.10.4
>From 889541a5faf5678d920cf07d5f3b8e312817105c Mon Sep 17 00:00:00 2001
From: David Lechner <david at lechnology.com>
Date: Wed, 20 Feb 2013 14:57:58 -0600
Subject: [PATCH 2/2] make void marshall_ValueListItem(Marshall *m) use copies
of list items instead of the list items themselves so
that the items are not destroyed when the list is
destroyed
---
assemblies/qyoto-qtcore/native/marshall_macros.h | 28 ++++++++++++++--------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/assemblies/qyoto-qtcore/native/marshall_macros.h b/assemblies/qyoto-qtcore/native/marshall_macros.h
index ba6b932..4c2d204 100644
--- a/assemblies/qyoto-qtcore/native/marshall_macros.h
+++ b/assemblies/qyoto-qtcore/native/marshall_macros.h
@@ -104,6 +104,14 @@ void marshall_ItemList(Marshall *m) {
#define DEF_LIST_MARSHALLER(ListIdent,ItemList,Item) namespace { char ListIdent##STR[] = #Item; } \
Marshall::HandlerFn marshall_##ListIdent = marshall_ItemList<Item,ItemList,ListIdent##STR>;
+
+
+// A ValueListItem means that the Item in ItemList uses implicit sharing, i.e. the class inherits
+// QSharedData. So, when marshalling ToObject, we will create a copy of each item in the list and pass
+// the copy back to C# rather than the object itself.
+//
+// See http://doc.qt.digia.com/stable/implicit-sharing.html for more info on implicit sharing.
+
template <class Item, class ItemList, const char *ItemSTR >
void marshall_ValueListItem(Marshall *m) {
switch(m->action()) {
@@ -119,21 +127,21 @@ void marshall_ValueListItem(Marshall *m) {
for (int i = 0; i < list->size(); ++i) {
void* obj = list->at(i);
smokeqyoto_object * o = (smokeqyoto_object*) (*GetSmokeObject)(obj);
-
+
void* ptr = o->ptr;
ptr = o->smoke->cast(
ptr, // pointer
o->classId, // from
o->smoke->idClass(ItemSTR).index // to
);
-
+
cpplist->append(*(Item*) ptr);
(*FreeGCHandle)(obj);
}
-
+
m->item().s_voidp = cpplist;
m->next();
-
+
delete list;
(*FreeGCHandle)(m->var().s_voidp);
@@ -142,7 +150,7 @@ void marshall_ValueListItem(Marshall *m) {
}
}
break;
-
+
case Marshall::ToObject:
{
ItemList *valuelist = (ItemList*)m->item().s_voidp;
@@ -153,7 +161,7 @@ void marshall_ValueListItem(Marshall *m) {
Smoke::ModuleIndex ix = m->smoke()->findClass(ItemSTR);
const char * className = qyoto_modules[ix.smoke].binding->className(ix.index);
-
+
void * al = (*ConstructList)(className);
for (int i=0; i < valuelist->size() ; ++i) {
@@ -161,8 +169,9 @@ void marshall_ValueListItem(Marshall *m) {
void * obj = (*GetInstance)(p, true);
if (obj == 0) {
- smokeqyoto_object * o = alloc_smokeqyoto_object(false, ix.smoke, ix.index, p);
- obj = (*CreateInstance)(qyoto_resolve_classname(o), o);
+ p = (void *) new Item(*(Item*) p);
+ smokeqyoto_object * o = alloc_smokeqyoto_object(false, ix.smoke, ix.index, p);
+ obj = (*CreateInstance)(qyoto_resolve_classname(o), o);
}
(*AddIntPtrToList)(al, obj);
@@ -175,11 +184,10 @@ void marshall_ValueListItem(Marshall *m) {
if (m->type().isStack()) {
delete valuelist;
}
-
}
break;
-
+
default:
m->unsupported();
break;
--
1.7.10.4
More information about the Kde-bindings
mailing list