Welcome! Log In Create A New Profile

Advanced

emit QStringList

Posted by ShaunGVW 
Announcements Last Post
Announcement SoC Curricula 09/30/2017 01:08PM
Announcement Demarcation or scoping of examinations and assessment 02/13/2017 07:59AM
Announcement School of Computing Short Learning Programmes 11/24/2014 08:37AM
Announcement Unisa contact information 07/28/2011 01:28PM
emit QStringList
July 18, 2009 10:38AM
I am busy writing a program (C++/Qt) and have made use of threading. In the thread, I want to return a QStringList of values to the original program that set up thh thread. In the Primes question, I used this method to return primes to the calling program, but it was of type int. Now though, I have a QStringList that I want to return, but it gives errors. Can a QStringList not be returned like this? What is the best way to get the values back? A pointer to the QStringList?

I have declared the QStringList as private in my class. I have attempted to redefine it as a pointer, but I'm not so strong in pointers. How do I then append to it. Declared as it is, I simply say m_QSLVariable<<newValue to append, but if I declared it as QStringList *QSLVariable, how would I do it? And then how do I return this back to the calling program? This will hold MANY values (I know, not ideal to have it all in memory, but okay for now - testing phase still), and so I don't want to return it by value either, so eventually I would have to destroy it too to reclaim the memory. I think this will go a far way in clearing things up for me.

Any help/pointers (smile) appreciated!

I must say, I am really enjoying Qt now that I slowly getting the gist of it, I am not so confused. As opposed to the beginning of the year, I was totally lost. This is just a word of encouragement to anyone finding this course very difficult. It takes a lot of time and effort.

Thanks.
avatar Re: emit QStringList
July 19, 2009 12:49AM
I'm not to sure of the intricacies of threading myself but it would help if you pasted the actual error messages you received.

You mention using a pointer to hold your values in your thread. You can still add to the list by using the append(const T &value) function that QStringList inherits from QList<typename T> class. Another thing you could also try is to setting the stringlist up as a a normal variable and then passing a reference back instead of a pointer.

One thing you must do though, since you want the list accessible by two different threads, is to setup a Mutex to guard the read/write accesses. The Qt Reference doesn't say that QStringList is thread-safe so assume it's not.
Anonymous User
Re: emit QStringList
July 19, 2009 09:23AM
I created separate methods to generate values that were passed to a list pane (pane.add(value)). I made use of signals and slots to pass those values about. I used run() to kick off the thread. What I failed to do was to be able to have those threads run concurrently. Calling run twice just augmented my one thread confused smiley. I never had time and submitted an incomplete question.
Re: emit QStringList
July 19, 2009 09:41AM
Each thread that is created, I would assume it creates its own instance of a QStringList. So I'm a bit hesitant to try start learning about Mutex's at this point. Still just trying to understand basic threading.
Setting up the QStringList as a standard variable is exactly what I want to do, and what I initially attempted. How do I pass the reference back?

This is how I originally tried it, and the errors it raised...

[in .h file]
signals:
void processed(QStringList processedFile);

[in c++ file]
emit processed(processedFile);

Errors...
invalid use of undefined type `struct QStringList'
forward declaration of `struct QStringList
initializing argument 1 of `void Pitch::processed(QStringList)'
'_t1' has incomplete type
forward declaration of `struct QStringList'

What I was trying, is to populate a QStringList and emit it as a signal. This QStringList has local scope to the method, and declared as "QStringList processedFile;" Now it would be quite big, so I would rather pass it as reference, so I try the following...

[in .h file]
signals:
void processed(QStringList &processedFile);

[in c++ file]
emit processed(&processedFile);

(I still leave the declaration as "QStringList processedFile;" within the method.)
...because now I just want to emit the address of the QStringList. I now get the following error...

Errors...
no matching function for call to `Pitch::processed(QStringList*)'

So now I'm not sure what I'm doing wrong. In my originating thread instantiating class, I would, based on what I think is the right way to do this, then assign this emited address to a pointer, which would then supposedly have access to the QStringList contents. Just a question on this, does each class instantiation have its own memory allocated to it? And is this available to other classes, or would there be some kinf of offset to take into account?

Thanks.
avatar Re: emit QStringList
July 19, 2009 03:23PM
@Rick

It sounds like you only one instance of your thread and you tried to run() the same instance twice. If you want two threads, you need two instances.

Language: C++ (QT)
PrimeThread panel1, panel2;   panel1.run(); // starts the first thread panel2.run(); // starts the second thread, independantly of the first one

@ShaunGWV

errors like "undefined type xxx" usually mean you haven't included a necessary header file somewhere.

When you're passing by reference, don't pass the address of the object you're passing. If you use the address operator (eg. emit processed(&processedFile) ) the compiler is going to expect the receiving function to want a pointer. What you need to do is just pass the variable like you would normally pass it (eg. emit processed(processedFile) ).

It seems you don't have a complete understanding of the three ways of passing values. I'll try and make it simple.

Passing by value:

Language: C++
function passByValue(MyClass funcObject);   main(){ MyClass stackObject, *heapObject; heapObject = new MyClass;   passByValue(stackObject); passByValue(*heapObject);   delete heapObject; }

With this kind of argument passing, a copy of the object/variable is made. This means that funcObject is a completely separate entity to what was passed through and takes up its own piece of memory. It is important to note here that in order to create funcObject, a copy of the original object is created using the copy constructor of MyClass (ie MyClass:: MyClass(const MyClass &other) ). If your class does not have a copy constructor, the compiler will create a simple one for you.

Before passing in pointer objects, they need to be dereferenced first using the dereference operator ( * ) so that the object being pointed to is copied and not the pointer itself.

This may sound like a good idea but there are pitfalls. The compiler-created copy constructor only does a shallow copy. What this means is that the data members are copied. If any of those data members are references or pointers, the objects they're pointing to are not copies, only the references to them. This means that there will now be two objects referencing the same things. This is not necessarily a bad thing but it is a potential point for bugs.

A general rule of thumb is that , if you have references or pointers as data members, create your own copy constructor that creates a deep copy of your objects. On that note, when creating a copy constructor, it's a good idea to create an assignment operator overload too (e.g MyClass:: operator= (const MyClass &other) )

Passing by pointer

Language: C++
function passByPointer(MyClass *funcObject);   main () { MyClass stackObject, *heapObject;   heapObject = new MyClass;   passByPointer(&stackObject); passByPointer(heapObject);   delete heapObject; }

Passing objects around relieves the burden of worrying about copy constructors because the only thing that's passed around is the memory address of the object that's already been created. In the case of stackObject above, the object was created on the stack frame of function main(), this means that it is automatically allocated memory, created and destroyed (when the function exits). You have direct access to the object so if you want to pass it to function passByPointer, you need to get it's address and pass that first, by using the address-of operator.

When creating objects in heap memory, you don't have direct access to the object itself only the memory address thereof via a pointer. You have to create it yourself using new and destroy it yourself using delete. To access any of it's members, you need to use the address resolution operator ( -> ) or a combination of the dereference operator ( * ) and the member resolution operator ( . ). You can pass heapObject directly to passByPointer because it's already a pointer.

A disadvantage with pointers is that you have to manage your memory so you don't lose track of your heap objects (memory leak), try to delete the same object twice (double deleting) or try and access memory that's invalid (buffer overruns).

Passing by reference

Language: C++
function passByReference(MyClass &funcObject);   main () { MyClass stackObject, *heapObject; heapObject = new MyClass;   passByReference(stackObject); passByReference(*heapObject);   delete heapObject; }

The first two methods of passing arguments come from C but passing by reference was introduced in C++. It is somewhat a fusion of the two methods; you pass arguments like you would when passing by value BUT they are handled by the system similarly to pointers since no copying is done, only a reference is passed.

There are a few significant difference between references and pointers though. One important one is that they HAVE TO be initialised. For a stack object, this must be done when the reference is defined.

Language: C++
int i; int &p = i; int &q; // illegal

Care must also be taken when a data member of a class is a reference. This must be initialised in the member initialisation list. It cannot be initialised in the constructor since this is too late.

Language: C++
class MyClass{ public: MyClass(OtherClass &obj) : refObject(obj) { }   private: OtherClass &refObject; };
avatar Re: emit QStringList
July 20, 2009 01:34PM
Sorry Rick,

That should read:

Language: C++ (QT)
panel1.start(); panel2.start();


You should never call run() yourself. It gets called internally once the operating system-dependant thread has been created.
Re: emit QStringList
July 21, 2009 12:43PM
Found my problem.
I had to declare class <QStringList> before my header definition.
Anonymous User
Re: emit QStringList
July 21, 2009 01:06PM
Anonymous User
Re: emit QStringList
July 21, 2009 01:12PM
can one pass things like QStringList around with signals and slots?
Re: emit QStringList
July 21, 2009 08:21PM
It appears so. Although if large, pass by reference would be better. So says the lecturer! drinking smiley
avatar Re: emit QStringList
July 25, 2009 11:21AM
@ShaunGWV

With the STL, a lot of classes' definitions were interlinked so you could include one header and you'd get access to a whole bunch of classes. I read somewhere that the convention used by Qt is that each class must be separated from all others. As such, if that class' definition doesn't rely on another class but you do, you'll have to include both headers. I've found that my inclusion lists are much longer than they used to be when using the STL or other libraries.

One way around this is to include the module header instead of the individual classes. this would be something like "#include <QtCore>" or "#include <QtXml>". That way you get all the public classes inside that module. This is a bit of overkill though since the compiler has to process all those header files everytime you compile.

Another trick you can use if you have something like this:

Language: C++ (QT)
/// header file #include <QStringList>   class MyClass { // ????   public signals: void listComplete(QStringList &list);   // ????? };


Since you're declaring a function that uses a reference (or a pointer), you don't really need to include the entire definition in the header. You only need to include the definition when you need to use function or data members. If you're just passing classes around, you only need to tell the compiler that it exists somewhere.

Language: C++ (QT)
class QStringList; // class declaration. Tells the compiler that the class exists but it';s defined elsewhere class MyClass { // ???   public signals: void listComplete(QStringList &list);   // ??? };

You have to include the QStringList header in the sourcefile though because it will be used there.

The advantage to this kind of trick is that it shortens the compile time. The only time that the QStringList header is processed is when you are compiling the source file for MyClass. All other files that include your MyClass header file don't process it. In the first version, if 10 other files include the MyClass header, the QStringList header would also be included 10 times and processed 10 times.
Re: emit QStringList
July 26, 2009 08:16AM
Thanks for that. thumbs up
Sorry, only registered users may post in this forum.

Click here to login