Salut,
S�mantiquement le but est de faire �a :
Sauf que �a ne fonctionne pas.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <gcroot.h> void Test (String ^% k) { k = "apres"; } int main(array<System::String ^> ^args) { gcroot<String^> ungcroot = "avant"; Test(ungcroot); String ^res = ungcroot; // res == "apres" return 0; }
La solution que j'ai trouv�e :
Une autre solution ?
Code : 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 #include <gcroot.h> template <typename T> union Dummy { // pour récupérer le champ caché _handle de la structure gcroot gcroot<T>& g; void *ptr; Dummy(gcroot<T>& g) : g(g) {} }; template <typename T> T% Gcroot2TrackingReference(gcroot<T>& x) { Dummy<T> d(x); /// x est un pointeur sur gcroot, /// un gcroot est un pointeur sur Object^ return **(T**) d.ptr; // d'où ce cast } void Test (String ^% k) { k = "apres"; } int main(array<System::String ^> ^args) { gcroot<String^> s = "avant"; Test(Gcroot2TrackingReference(s)); String^ res = s; // res == "apres" return 0; }
Je peux argumenter sur le fait que c'est 100% safe de faire �a avec l'impl�mentation actuelle de la CLR :
- un Object ^ est un pointeur dont l'emplacement (l'adresse) est toujours connue de la CLR, qui modifiera sa valeur si elle le souhaite avec ses histoires de d�placement d'objets dans le tas manag�. Seules les fonctions __clrcall peuvent mettre un Object^ sur la pile C++ habituelle : la CLR sait retrouver toutes les fonctions __clrcall de la callstack.
- un Object^% est une r�f�rence sur Object^ donc c'est l'adresse d'un Object^. Deux cas se pr�sentent : le Object^ est sur la pile C++ et ne bougera pas, le Object^% est alors une r�f�rence C++ normale. Ou bien le Object^ est un champ d'un objet manag�, et alors Object^% est une tracking r�f�rence. La CLR n'a pas de raison de pr�sumer d'o� est la pile C++. Elle sait juste reconna�tre quand une adresse est dans le tas manag� ou non. Un Object^% peut lui �tre situ� n'importe o�, et l'Object^ r�f�renc� �galement (alors que l'Object lui est forc�ment dans le tas manag�).
- un gcroot est un pointeur sur Object^, Object^ qui lui est situ� � un emplacement (plus ou moins allou� dynamiquement) connu de la CLR.
le gcroot peut �tre situ� n'importe o�, comme un Object^%.- La seule diff�rence entre un gcroot et une tracking reference c'est qu'un gcroot pointe toujours sur un Object^ situ� dans cet emplacement connu de la CLR et allou� dynamiquement, alors qu'une tracking r�f�rence pointe sur un Object^ situ� n'importe o�.
- Donc caster un gcroot en Object^% n'est pas unsafe. L'inverse l'est peut-�tre.
Partager