Bonjour,

c'est encore moi :p

Contexte:



Résumé:

  • - En résumé il s'agit d'un exemple de producteur / consommateur basique. Le producteur produit un certain nombre d'éléments mis dans un QByteArray (cet objet QByteArray est propriété du producteur) et le consommateur prend des éléments de ce tableau.
  • - Le producteur passe le QByteArray au consommateur via un signal. Le consommateur agit ensuite sur l'objet QByteArray.


Problème: L'objet reçu par le consommateur (le QByteArray) contient bien les bonnes donnée, mais (c'est là que ce situe le coeur du problème) si l'exemple fonctionne en C++, en python l'objet n'est pas le même, il s'agit d'une copie => résultat, toute action du consommateur sur le QByteArray n'est pas répercutée sur l'objet appartenant au producteur puisque le consommateur reçoit une copie de l'objet et non l'objet lui-même.

Notez que je parle de copie parce que l'id() de l'objet n'est pas le même entre celui du producteur et celui du consommateur. J'ai légèrement changé le code de façon a voir l'id() du QByteArray pour le producteur et le consommateur.

question: comment faire pour recevoir exactement le même objet entre le producteur et le consommateur, sans (a priori) recevoir une copie ?

Output du programme: (notez 'id' ci-dessous qui est différent entre le producteur et le consommateur, alors qu'il "devrait" s'agir du même objet):

In produce. Data Type: <class 'PyQt4.QtCore.QByteArray'> - id: 41177992 - Size: 0
Producer: produced 7890 more bytes, 7890 of 123456 total

In consume. Data Type: <class 'PyQt4.QtCore.QByteArray'> - id: 41178096 - Size: 7890
In Consume: 0
Consumer: consumed 7890 more bytes, 7890 of 123456 total

In produce. Data Type: <class 'PyQt4.QtCore.QByteArray'> - id: 41177992 - Size: 7890

Producer: Consumer failed to consume!
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
 
import sys
from PyQt4 import QtCore
from PyQt4.QtCore import pyqtSlot
 
Limit = 123456
BlockSize = 7890
 
class Producer(QtCore.QObject):
 
    produced = QtCore.pyqtSignal(QtCore.QByteArray)
    finished = QtCore.pyqtSignal()
 
    def __init__(self, parent = None):
        super(Producer, self).__init__(parent)
 
        self.bytes = 0
        self.data = QtCore.QByteArray()
 
    @pyqtSlot()
    def produce(self):
        print("In produce. Data Type: {} - id: {} - Size: {}".format(type(self.data), id(self.data), self.data.size()))
 
        remaining = Limit - self.bytes
        if remaining == 0:
            self.finished.emit()
            return
 
        #this will never happen
        if self.data.size() != 0:
            QtCore.qFatal("Producer: Consumer failed to consume!")
 
        size = qMin(BlockSize, remaining)
        self.bytes += size
        remaining -= size
        self.data.fill("Q", size)
 
        print("Producer: produced {} more bytes, {} of {} total".format(size, self.bytes, Limit))
        self.produced.emit(self.data)
 
class Consumer(QtCore.QObject):
 
    consumed = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()
 
    def __init__(self, parent = None):
        super(Consumer, self).__init__(parent)
 
        self.bytes = 0
 
    @pyqtSlot("QByteArray")
    def consume(self, data):
        print("In consume. Data Type: {} - id: {} - Size: {}".format(type(data), id(data), data.size()))
 
        if data.size() == 0:
            QtCore.qFatal("Consumer: Producer failed to produce!")
 
        remaining = Limit - self.bytes
        size = data.size()
        remaining -= size
        self.bytes += size
        data.clear()
        print("In Consume: ", data.size())
 
        print("Consumer: consumed {} more bytes, {} of {} total".format(size, self.bytes, Limit))
        self.consumed.emit()
 
        if remaining == 0:
            self.finished.emit()       
 
def qMin(a, b):
    return a if a < b else b
 
def main(argv):
    app = QtCore.QCoreApplication(argv)
 
    # create the producer and consumer and plug them together
    producer = Producer()
    consumer = Consumer()
 
    producer.connect(consumer, QtCore.SIGNAL("consumed()"), producer.produce)
    consumer.connect(producer, QtCore.SIGNAL("produced(QByteArray)"), consumer.consume)
 
    # they both got their own threads
    producerThread = QtCore.QThread()
    producer.moveToThread(producerThread)
 
    consumerThread = QtCore.QThread()
    consumer.moveToThread(consumerThread)
 
    # start producing once the producer's thread has started
    producer.connect(producerThread, QtCore.SIGNAL("started()"), producer.produce)
 
    # when the consumer is done, it stops its thread
    consumerThread.connect(consumer, QtCore.SIGNAL("finished()"), consumerThread.quit)
 
    # when producer thread is done, it quits the application
    app.connect(producerThread, QtCore.SIGNAL("finished()"), app.quit)
 
    # go!
    producerThread.start()
    consumerThread.start()    
 
    app.exec_()    
 
if __name__ == '__main__':
    main(sys.argv)

Merci beaucoup pour votre aide !