C'est un peu HS puisqu'en l'occurence les pointeurs intelligents sont des
CComPtr, issus de la bibliothèque ATL, et qui permet de gérer des objets
COM.
Mais je pense que le principe est le même que pour des boost::shared_ptr
par exemple.
Passons au vif du sujet:
Pourquoi est ce que le code suivant ne fonctionne pas?
Est-ce qu'il existe une autre manière de passer des CComPtr en
paramètre de fonction?
class toto
{
private:
CComPtr<IGraphBuilder> pGraph;
public:
void SetGraph(CComPtr<IGraphBuilder> graph)
{
pGraph = graph;
}
};
C'est un peu HS puisqu'en l'occurence les pointeurs intelligents sont des CComPtr, issus de la bibliothèque ATL, et qui permet de gérer des objets COM.
Mais je pense que le principe est le même que pour des boost::shared_ptr par exemple.
Peut-être. Comment est supposé fonctionner un CComPtr ?
La documentation msdn (http://msdn2.microsoft.com/en-us/library/ezzw7k98.aspx) n'est pas très claire.
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de référence avec AddRef() qui incrémente le compteur et Release() qui le décrémente ?
Dans ce cas là, il est normal que la destruction d'un CComPtr déclenche un Release() mais ce Release ne devrait pas avoir d'effet s'il a été précédé d'un AddRef() (dans le constructeur ou l'opérateur =).
En tout cas, c'est ce que (me) suggère le code de CComPtr et de sa classe de base CComPtrBase qui ne semblent embarquer ni l'un ni l'autre un compteur de référence, mais qui semblent utiliser AddRef() et Release() pour ce but. Mais comme je ne connais pas COM, je ne suis pas certain de ce que doivent faire AddRef() et Release().
Voilà le code :
template <class T> class CComPtrBase { protected: CComPtrBase() throw() { p = NULL; } CComPtrBase(__in int nNull) throw() { ATLASSERT(nNull == 0); (void)nNull; p = NULL; } CComPtrBase(__in T* lp) throw() { p = lp; if (p != NULL) p->AddRef(); } public: typedef T _PtrClass; ~CComPtrBase() throw() { if (p) p->Release(); } operator T*() const throw() { return p; } T& operator*() const { ATLENSURE(p!=NULL); return *p; } //The assert on operator& usually indicates a bug. If this is really //what is needed, however, take the address of the p member explicitly. T** operator&() throw() { ATLASSERT(p==NULL); return &p; } _NoAddRefReleaseOnCComPtr<T>* operator->() const throw() { ATLASSERT(p!=NULL); return (_NoAddRefReleaseOnCComPtr<T>*)p; } bool operator!() const throw() { return (p == NULL); } bool operator<(__in_opt T* pT) const throw() { return p < pT; } bool operator!=(__in_opt T* pT) const { return !operator==(pT); } bool operator==(__in_opt T* pT) const throw() { return p == pT; }
// Release the interface and set to NULL void Release() throw() { T* pTemp = p; if (pTemp) { p = NULL; pTemp->Release(); } } // Compare two objects for equivalence bool IsEqualObject(__in_opt IUnknown* pOther) throw() { if (p == NULL && pOther == NULL) return true; // They are both NULL objects
if (p == NULL || pOther == NULL) return false; // One is NULL the other is not
C'est un peu HS puisqu'en l'occurence les pointeurs intelligents sont des
CComPtr, issus de la bibliothèque ATL, et qui permet de gérer des objets
COM.
Mais je pense que le principe est le même que pour des boost::shared_ptr
par exemple.
Peut-être. Comment est supposé fonctionner un CComPtr ?
La documentation msdn
(http://msdn2.microsoft.com/en-us/library/ezzw7k98.aspx) n'est pas très
claire.
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de
référence avec AddRef() qui incrémente le compteur et Release() qui le
décrémente ?
Dans ce cas là, il est normal que la destruction d'un CComPtr déclenche
un Release() mais ce Release ne devrait pas avoir d'effet s'il a été
précédé d'un AddRef() (dans le constructeur ou l'opérateur =).
En tout cas, c'est ce que (me) suggère le code de CComPtr et de sa
classe de base CComPtrBase qui ne semblent embarquer ni l'un ni l'autre
un compteur de référence, mais qui semblent utiliser AddRef() et
Release() pour ce but. Mais comme je ne connais pas COM, je ne suis pas
certain de ce que doivent faire AddRef() et Release().
Voilà le code :
template <class T>
class CComPtrBase
{
protected:
CComPtrBase() throw()
{
p = NULL;
}
CComPtrBase(__in int nNull) throw()
{
ATLASSERT(nNull == 0);
(void)nNull;
p = NULL;
}
CComPtrBase(__in T* lp) throw()
{
p = lp;
if (p != NULL)
p->AddRef();
}
public:
typedef T _PtrClass;
~CComPtrBase() throw()
{
if (p)
p->Release();
}
operator T*() const throw()
{
return p;
}
T& operator*() const
{
ATLENSURE(p!=NULL);
return *p;
}
//The assert on operator& usually indicates a bug. If this is really
//what is needed, however, take the address of the p member explicitly.
T** operator&() throw()
{
ATLASSERT(p==NULL);
return &p;
}
_NoAddRefReleaseOnCComPtr<T>* operator->() const throw()
{
ATLASSERT(p!=NULL);
return (_NoAddRefReleaseOnCComPtr<T>*)p;
}
bool operator!() const throw()
{
return (p == NULL);
}
bool operator<(__in_opt T* pT) const throw()
{
return p < pT;
}
bool operator!=(__in_opt T* pT) const
{
return !operator==(pT);
}
bool operator==(__in_opt T* pT) const throw()
{
return p == pT;
}
// Release the interface and set to NULL
void Release() throw()
{
T* pTemp = p;
if (pTemp)
{
p = NULL;
pTemp->Release();
}
}
// Compare two objects for equivalence
bool IsEqualObject(__in_opt IUnknown* pOther) throw()
{
if (p == NULL && pOther == NULL)
return true; // They are both NULL objects
if (p == NULL || pOther == NULL)
return false; // One is NULL the other is not
C'est un peu HS puisqu'en l'occurence les pointeurs intelligents sont des CComPtr, issus de la bibliothèque ATL, et qui permet de gérer des objets COM.
Mais je pense que le principe est le même que pour des boost::shared_ptr par exemple.
Peut-être. Comment est supposé fonctionner un CComPtr ?
La documentation msdn (http://msdn2.microsoft.com/en-us/library/ezzw7k98.aspx) n'est pas très claire.
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de référence avec AddRef() qui incrémente le compteur et Release() qui le décrémente ?
Dans ce cas là, il est normal que la destruction d'un CComPtr déclenche un Release() mais ce Release ne devrait pas avoir d'effet s'il a été précédé d'un AddRef() (dans le constructeur ou l'opérateur =).
En tout cas, c'est ce que (me) suggère le code de CComPtr et de sa classe de base CComPtrBase qui ne semblent embarquer ni l'un ni l'autre un compteur de référence, mais qui semblent utiliser AddRef() et Release() pour ce but. Mais comme je ne connais pas COM, je ne suis pas certain de ce que doivent faire AddRef() et Release().
Voilà le code :
template <class T> class CComPtrBase { protected: CComPtrBase() throw() { p = NULL; } CComPtrBase(__in int nNull) throw() { ATLASSERT(nNull == 0); (void)nNull; p = NULL; } CComPtrBase(__in T* lp) throw() { p = lp; if (p != NULL) p->AddRef(); } public: typedef T _PtrClass; ~CComPtrBase() throw() { if (p) p->Release(); } operator T*() const throw() { return p; } T& operator*() const { ATLENSURE(p!=NULL); return *p; } //The assert on operator& usually indicates a bug. If this is really //what is needed, however, take the address of the p member explicitly. T** operator&() throw() { ATLASSERT(p==NULL); return &p; } _NoAddRefReleaseOnCComPtr<T>* operator->() const throw() { ATLASSERT(p!=NULL); return (_NoAddRefReleaseOnCComPtr<T>*)p; } bool operator!() const throw() { return (p == NULL); } bool operator<(__in_opt T* pT) const throw() { return p < pT; } bool operator!=(__in_opt T* pT) const { return !operator==(pT); } bool operator==(__in_opt T* pT) const throw() { return p == pT; }
// Release the interface and set to NULL void Release() throw() { T* pTemp = p; if (pTemp) { p = NULL; pTemp->Release(); } } // Compare two objects for equivalence bool IsEqualObject(__in_opt IUnknown* pOther) throw() { if (p == NULL && pOther == NULL) return true; // They are both NULL objects
if (p == NULL || pOther == NULL) return false; // One is NULL the other is not
Après l'appel de t.SetGraph(pGraph), un appel à IGraphBuilder::Release() est déclenché, ce qui fait que mon objet pGraph est réinitialisé...
je ne pense pas que toto::pGraph soit réinitialisé.
avant point: il manque quelque chose dans le constructeur de foo() car ici aucun objet COM implémentant IGraphBuilder n'est construit; avec cette écriture pGraph est un ComPtr contenant un pointeur d'interface nul. il faudrait un: pGraph.CoCreateInstance(CLSID_???); avant l'appel à toto::setGraph
en supposant foo::pGraph créé (son ref count est à 1 après CoCreateInstance):
- l'appel à toto::setGraph utilise un paramètre par valeur donc une copie de pGraph est réalisée, ceci consiste à incrémenter son ref count (=2) avant d'appeler setGraph avec cette "copie" (fausse copie car c'est bien la même instance d'interface)
- dans toto::setGraph tu affectes ce param reçu à toto::pGraph, toto:pGrapg est alors releasé, s'il existe, car il ne peut plus être référencé par toto, puis l'interface reçue "graph" est incrémentée (=3) et stocké dans pGraph ** ça là où le ComPtr sert, il évite d'avoir à tester le pGraph local et le releasé si on l'avait référencé; ComPtr ne sert qu'à gérer les addRef, Release à notre place **
- au retour de setGraph le paramètre temporaire transmis est "détruit" par un release (=2), on a bien /un/ IGraphBuilder::Release mais 2 AddRef
interface est bien référencée par toto::pGraph et foo::pGraph (même si, sur la portion de code vue, cela semble bizarre de transmettre à une instance membre une autre donnée membre; toto a ebvie d'être vu comme une inner classe utilitaire se chargeant de la réalisation complète du travail).
Sylvain.
Michael wrote on 23/06/2006 13:34:
Après l'appel de t.SetGraph(pGraph), un appel à
IGraphBuilder::Release() est déclenché, ce qui fait que mon objet
pGraph est réinitialisé...
je ne pense pas que toto::pGraph soit réinitialisé.
avant point: il manque quelque chose dans le constructeur de foo() car
ici aucun objet COM implémentant IGraphBuilder n'est construit; avec
cette écriture pGraph est un ComPtr contenant un pointeur d'interface nul.
il faudrait un: pGraph.CoCreateInstance(CLSID_???); avant l'appel à
toto::setGraph
en supposant foo::pGraph créé (son ref count est à 1 après
CoCreateInstance):
- l'appel à toto::setGraph utilise un paramètre par valeur donc une
copie de pGraph est réalisée, ceci consiste à incrémenter son ref count
(=2) avant d'appeler setGraph avec cette "copie" (fausse copie car c'est
bien la même instance d'interface)
- dans toto::setGraph tu affectes ce param reçu à toto::pGraph,
toto:pGrapg est alors releasé, s'il existe, car il ne peut plus être
référencé par toto, puis l'interface reçue "graph" est incrémentée (=3)
et stocké dans pGraph
** ça là où le ComPtr sert, il évite d'avoir à tester le pGraph local et
le releasé si on l'avait référencé; ComPtr ne sert qu'à gérer les
addRef, Release à notre place **
- au retour de setGraph le paramètre temporaire transmis est "détruit"
par un release (=2), on a bien /un/ IGraphBuilder::Release mais 2 AddRef
interface est bien référencée par toto::pGraph et foo::pGraph
(même si, sur la portion de code vue, cela semble bizarre de transmettre
à une instance membre une autre donnée membre; toto a ebvie d'être vu
comme une inner classe utilitaire se chargeant de la réalisation
complète du travail).
Après l'appel de t.SetGraph(pGraph), un appel à IGraphBuilder::Release() est déclenché, ce qui fait que mon objet pGraph est réinitialisé...
je ne pense pas que toto::pGraph soit réinitialisé.
avant point: il manque quelque chose dans le constructeur de foo() car ici aucun objet COM implémentant IGraphBuilder n'est construit; avec cette écriture pGraph est un ComPtr contenant un pointeur d'interface nul. il faudrait un: pGraph.CoCreateInstance(CLSID_???); avant l'appel à toto::setGraph
en supposant foo::pGraph créé (son ref count est à 1 après CoCreateInstance):
- l'appel à toto::setGraph utilise un paramètre par valeur donc une copie de pGraph est réalisée, ceci consiste à incrémenter son ref count (=2) avant d'appeler setGraph avec cette "copie" (fausse copie car c'est bien la même instance d'interface)
- dans toto::setGraph tu affectes ce param reçu à toto::pGraph, toto:pGrapg est alors releasé, s'il existe, car il ne peut plus être référencé par toto, puis l'interface reçue "graph" est incrémentée (=3) et stocké dans pGraph ** ça là où le ComPtr sert, il évite d'avoir à tester le pGraph local et le releasé si on l'avait référencé; ComPtr ne sert qu'à gérer les addRef, Release à notre place **
- au retour de setGraph le paramètre temporaire transmis est "détruit" par un release (=2), on a bien /un/ IGraphBuilder::Release mais 2 AddRef
interface est bien référencée par toto::pGraph et foo::pGraph (même si, sur la portion de code vue, cela semble bizarre de transmettre à une instance membre une autre donnée membre; toto a ebvie d'être vu comme une inner classe utilitaire se chargeant de la réalisation complète du travail).
Sylvain.
Michael
(même si, sur la portion de code vue, cela semble bizarre de transmettre à une instance membre une autre donnée membre; toto a ebvie d'être vu comme une inner classe utilitaire se chargeant de la réalisation complète du travail).
C'est exactement cela... toto initialise une partie du travail à faire sur pGraph.
J'ai aussi une deuxième classe, disons toto2, membre de foo, à qui je passe également le membre pGraph.
Et je mets en relation ces deux classes avec un toto.Connect(toto2) pour qu'elles se mettent en relation l'une avec l'autre...
Ca te semble bizarre parce qu'il existe une manière de faire plus correcte?
(même si, sur la portion de code vue, cela semble bizarre de transmettre
à une instance membre une autre donnée membre; toto a ebvie d'être vu
comme une inner classe utilitaire se chargeant de la réalisation
complète du travail).
C'est exactement cela... toto initialise une partie du travail à faire sur
pGraph.
J'ai aussi une deuxième classe, disons toto2, membre de foo, à qui je passe
également le membre pGraph.
Et je mets en relation ces deux classes avec un toto.Connect(toto2) pour
qu'elles se mettent en relation l'une avec l'autre...
Ca te semble bizarre parce qu'il existe une manière de faire plus correcte?
(même si, sur la portion de code vue, cela semble bizarre de transmettre à une instance membre une autre donnée membre; toto a ebvie d'être vu comme une inner classe utilitaire se chargeant de la réalisation complète du travail).
C'est exactement cela... toto initialise une partie du travail à faire sur pGraph.
J'ai aussi une deuxième classe, disons toto2, membre de foo, à qui je passe également le membre pGraph.
Et je mets en relation ces deux classes avec un toto.Connect(toto2) pour qu'elles se mettent en relation l'une avec l'autre...
Ca te semble bizarre parce qu'il existe une manière de faire plus correcte?
Michael
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de référence avec AddRef() qui incrémente le compteur et Release() qui le décrémente ?
C'est tout à fait ça...
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de
référence avec AddRef() qui incrémente le compteur et Release() qui le
décrémente ?
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de référence avec AddRef() qui incrémente le compteur et Release() qui le décrémente ?
C'est tout à fait ça...
Sylvain
Michael wrote on 25/06/2006 23:52:
Ca te semble bizarre parce qu'il existe une manière de faire plus correcte?
j'indiquais "au vu du fragment de code fourni".
si foo n'utilise pas souvent pGraph, elle pourrait le créer et le distribuer à toto, toto2, ..., même quitte à le redemander à son instance membre toto quand elle en a vraiment besoin.
au delà, si ces classes fournissent une implémentation de ton modèle fournisseur de data / visualisateur; je pense que le modèle évoluera encore car tu devras (dans le cadre d'utilisation de DX) en effet multiplier les objets utilitaires et tous leur communiquer ton interface de base - ce qui nuit forcément à l'isolation des roles.
enfin de mon expérience, hein ...
Sylvain.
Michael wrote on 25/06/2006 23:52:
Ca te semble bizarre parce qu'il existe une manière de faire plus correcte?
j'indiquais "au vu du fragment de code fourni".
si foo n'utilise pas souvent pGraph, elle pourrait le créer et le
distribuer à toto, toto2, ..., même quitte à le redemander à son
instance membre toto quand elle en a vraiment besoin.
au delà, si ces classes fournissent une implémentation de ton modèle
fournisseur de data / visualisateur; je pense que le modèle évoluera
encore car tu devras (dans le cadre d'utilisation de DX) en effet
multiplier les objets utilitaires et tous leur communiquer ton interface
de base - ce qui nuit forcément à l'isolation des roles.
Ca te semble bizarre parce qu'il existe une manière de faire plus correcte?
j'indiquais "au vu du fragment de code fourni".
si foo n'utilise pas souvent pGraph, elle pourrait le créer et le distribuer à toto, toto2, ..., même quitte à le redemander à son instance membre toto quand elle en a vraiment besoin.
au delà, si ces classes fournissent une implémentation de ton modèle fournisseur de data / visualisateur; je pense que le modèle évoluera encore car tu devras (dans le cadre d'utilisation de DX) en effet multiplier les objets utilitaires et tous leur communiquer ton interface de base - ce qui nuit forcément à l'isolation des roles.
enfin de mon expérience, hein ...
Sylvain.
Michael
au delà, si ces classes fournissent une implémentation de ton modèle fournisseur de data / visualisateur; je pense que le modèle évoluera encore car tu devras (dans le cadre d'utilisation de DX) en effet multiplier les objets utilitaires et tous leur communiquer ton interface de base - ce qui nuit forcément à l'isolation des roles.
Il est vrai que même si pour l'instant ce modèle est bien défini, il pourrait effectivement évoluer.
Mais je ne vois pas comment faire autrement.
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me semblait être de le créer avec la classe qui chapeaute le tout, et de le passer aux inner classes qui l'utilisent.
au delà, si ces classes fournissent une implémentation de ton modèle
fournisseur de data / visualisateur; je pense que le modèle évoluera
encore car tu devras (dans le cadre d'utilisation de DX) en effet
multiplier les objets utilitaires et tous leur communiquer ton interface
de base - ce qui nuit forcément à l'isolation des roles.
Il est vrai que même si pour l'instant ce modèle est bien défini, il pourrait
effectivement évoluer.
Mais je ne vois pas comment faire autrement.
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me
semblait être de le créer avec la classe qui chapeaute le tout, et de le
passer aux inner classes qui l'utilisent.
au delà, si ces classes fournissent une implémentation de ton modèle fournisseur de data / visualisateur; je pense que le modèle évoluera encore car tu devras (dans le cadre d'utilisation de DX) en effet multiplier les objets utilitaires et tous leur communiquer ton interface de base - ce qui nuit forcément à l'isolation des roles.
Il est vrai que même si pour l'instant ce modèle est bien défini, il pourrait effectivement évoluer.
Mais je ne vois pas comment faire autrement.
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me semblait être de le créer avec la classe qui chapeaute le tout, et de le passer aux inner classes qui l'utilisent.
Sylvain
Michael wrote on 26/06/2006 12:15:
Mais je ne vois pas comment faire autrement.
avec les "contraintes" DirectX je n'ai pas non plus vraiment réussi.
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me semblait être de le créer avec la classe qui chapeaute le tout, et de le passer aux inner classes qui l'utilisent.
et cela n'a pas de raison de ne pas être pertinent.
certains services peuvent déclarés comme un fournisseur/gérant d'interface à connecter (par le chapeau) à pGraph, mais d'autres ont des besoins qui justifient de posséder pGraph, so.
Sylvain.
Michael wrote on 26/06/2006 12:15:
Mais je ne vois pas comment faire autrement.
avec les "contraintes" DirectX je n'ai pas non plus vraiment réussi.
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me
semblait être de le créer avec la classe qui chapeaute le tout, et de le
passer aux inner classes qui l'utilisent.
et cela n'a pas de raison de ne pas être pertinent.
certains services peuvent déclarés comme un fournisseur/gérant
d'interface à connecter (par le chapeau) à pGraph, mais d'autres ont des
besoins qui justifient de posséder pGraph, so.
avec les "contraintes" DirectX je n'ai pas non plus vraiment réussi.
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me semblait être de le créer avec la classe qui chapeaute le tout, et de le passer aux inner classes qui l'utilisent.
et cela n'a pas de raison de ne pas être pertinent.
certains services peuvent déclarés comme un fournisseur/gérant d'interface à connecter (par le chapeau) à pGraph, mais d'autres ont des besoins qui justifient de posséder pGraph, so.
Sylvain.
Michael
Mais je ne vois pas comment faire autrement.
avec les "contraintes" DirectX je n'ai pas non plus vraiment réussi.
C'est rassurant alors ;)
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me semblait être de le créer avec la classe qui chapeaute le tout, et de le passer aux inner classes qui l'utilisent.
et cela n'a pas de raison de ne pas être pertinent.
Très bien, je garde donc ça en l'état...
Merci :)
Mais je ne vois pas comment faire autrement.
avec les "contraintes" DirectX je n'ai pas non plus vraiment réussi.
C'est rassurant alors ;)
L'objet pGraph doit être unique. Et la seule manière de le rendre
unique me semblait être de le créer avec la classe qui chapeaute le
tout, et de le passer aux inner classes qui l'utilisent.
et cela n'a pas de raison de ne pas être pertinent.
avec les "contraintes" DirectX je n'ai pas non plus vraiment réussi.
C'est rassurant alors ;)
L'objet pGraph doit être unique. Et la seule manière de le rendre unique me semblait être de le créer avec la classe qui chapeaute le tout, et de le passer aux inner classes qui l'utilisent.
et cela n'a pas de raison de ne pas être pertinent.
Très bien, je garde donc ça en l'état...
Merci :)
Arnaud Meurgues
Michael wrote:
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de référence avec AddRef() qui incrémente le compteur et Release() qui le décrémente ?
C'est tout à fait ça...
Mais du coup, je ne comprends pas pourquoi un appel à Release réinitialiserait l'objet. Ai-je raté quelque chose dans l'énoncé de la question ?
-- Arnaud
Michael wrote:
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de
référence avec AddRef() qui incrémente le compteur et Release() qui le
décrémente ?
C'est tout à fait ça...
Mais du coup, je ne comprends pas pourquoi un appel à Release
réinitialiserait l'objet.
Ai-je raté quelque chose dans l'énoncé de la question ?
N'est-ce pas plutôt l'objet COM lui-même qui gère son comptage de référence avec AddRef() qui incrémente le compteur et Release() qui le décrémente ?
C'est tout à fait ça...
Mais du coup, je ne comprends pas pourquoi un appel à Release réinitialiserait l'objet. Ai-je raté quelque chose dans l'énoncé de la question ?
-- Arnaud
Michael
Mais du coup, je ne comprends pas pourquoi un appel à Release réinitialiserait l'objet. Ai-je raté quelque chose dans l'énoncé de la question ?
Ben je ne suis pas sûr, mais je crois que, lorsque Release amène le compteur interne de l'objet COM IGraphBuilder à 0, celui-ci efface tous les filtres qui y sont connectés...
C'est ce que j'appelle réinitialiser. L'objet est toujours présent, mais vide. J'ai fait un abus de language en fait :)
Mais du coup, je ne comprends pas pourquoi un appel à Release
réinitialiserait l'objet.
Ai-je raté quelque chose dans l'énoncé de la question ?
Ben je ne suis pas sûr, mais je crois que, lorsque Release amène le compteur
interne de l'objet COM IGraphBuilder à 0, celui-ci efface tous les filtres
qui y sont connectés...
C'est ce que j'appelle réinitialiser. L'objet est toujours présent, mais
vide. J'ai fait un abus de language en fait :)
Mais du coup, je ne comprends pas pourquoi un appel à Release réinitialiserait l'objet. Ai-je raté quelque chose dans l'énoncé de la question ?
Ben je ne suis pas sûr, mais je crois que, lorsque Release amène le compteur interne de l'objet COM IGraphBuilder à 0, celui-ci efface tous les filtres qui y sont connectés...
C'est ce que j'appelle réinitialiser. L'objet est toujours présent, mais vide. J'ai fait un abus de language en fait :)