[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