convertir gcroot<String^> en String^%
Salut,
S�mantiquement le but est de faire �a :
Code:
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;
} |
Sauf que �a ne fonctionne pas.
La solution que j'ai trouv�e :
Code:
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;
} |
Une autre solution ?
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.