Comment copier efficacement BSTR dans wchar_t ?

J’ai un object BSTR que je voudrais convertir pour le copier en un object wchar__t. Le problème est que la longueur de l’object BSTR peut varier de quelques kilo-octets à quelques centaines de kilo-octets. Existe-t-il un moyen efficace de copier les données? Je sais que je pourrais simplement déclarer un tableau wchar_t et toujours allouer le maximum de données possible qu’il aurait besoin de contenir. Toutefois, cela signifierait l’allocation de centaines de kilo-octets de données pour une tâche pouvant éventuellement ne nécessiter que quelques kilo-octets. Aucune suggestion?

Tout d’abord, vous n’êtes peut-être pas obligé de faire quoi que ce soit, si tout ce que vous avez à faire est de lire le contenu. Un type BSTR est déjà un pointeur sur un tableau wchar_t à zéro. En fait, si vous consultez les en-têtes, vous constaterez que BSTR est essentiellement défini comme suit:

typedef BSTR wchar_t*; 

Ainsi, le compilateur ne peut pas les distinguer, même s’ils ont une sémantique différente.

Il y a deux mises en garde importantes.

  1. Les BSTR sont supposés être immuables. Vous ne devriez jamais changer le contenu d’un BSTR après son initialisation. Si vous le “changez”, vous devez en créer un nouveau, atsortingbuer le nouveau pointeur et relâcher l’ancien (si vous en êtes le propriétaire).
    [ UPDATE : ce n’est pas vrai; Pardon! Vous pouvez modifier les BSTR en place. J’ai très rarement eu le besoin.]

  2. Les BSTR sont autorisés à contenir des caractères nuls incorporés, contrairement aux chaînes C / C ++ traditionnelles.

Si vous avez assez de contrôle sur la source du BSTR et que vous pouvez garantir que le BSTR ne contient pas de NULL incorporée, vous pouvez lire le BSTR comme s’il s’agissait d’un wchar_t et utiliser les méthodes de chaîne conventionnelles (wcscpy, etc.) pour: y accéder. Sinon, votre vie devient plus difficile. Vous devrez toujours manipuler vos données sous forme de plusieurs BSTR ou d’un tableau de wchar_t alloué dynamicment. La plupart des fonctions liées aux chaînes ne fonctionneront pas correctement.

Supposons que vous contrôliez vos données ou ne vous inquiétez pas des valeurs NULL. Supposons également que vous devez vraiment faire une copie et que vous ne pouvez pas simplement lire le BSTR existant directement. Dans ce cas, vous pouvez faire quelque chose comme ceci:

 UINT length = SysSsortingngLen(myBstr); // Ask COM for the size of the BSTR wchar_t *mySsortingng = new wchar_t[lenght+1]; // Note: SysSsortingngLen doesn't // include the space needed for the NULL wcscpy(mySsortingng, myBstr); // Or your favorite safer ssortingng function // ... delete mySsortingng; // Done 

Si vous utilisez des wrappers de classe pour votre BSTR, le wrapper doit pouvoir appeler SysSsortingngLen () à votre place. Par exemple:

 CComBSsortingng use .Length(); _bstr_t use .length(); 

MISE À JOUR : C’est un bon article sur le sujet rédigé par une personne beaucoup plus informée que moi:
“Le guide complet de Eric [Lippert] sur la sémantique BSTR”

UPDATE : strcpy () remplacé par wcscpy () dans l’exemple

Les objects BSTR contiennent un préfixe de longueur, ce qui permet de déterminer que la longueur est bon marché. Déterminez la longueur, allouez un nouveau tableau assez grand pour contenir le résultat, calculez le résultat et souvenez-vous de le libérer lorsque vous avez terminé.

Il n’y a jamais besoin de conversion. Un pointeur BSTR pointe sur le premier caractère de la chaîne et est terminé par BSTR . La longueur est stockée avant le premier caractère en mémoire. BSTR sont toujours Unicode (UTF-16 / UCS-2). À un moment donné, il y avait quelque chose appelé “BSTR ANSI” – il y a quelques références dans les API héritées – mais vous pouvez les ignorer dans le développement actuel.

Cela signifie que vous pouvez passer un BSTR toute sécurité à toute fonction qui attend un wchar_t .

Dans Visual Studio 2008, vous pouvez obtenir une erreur de compilation, car BSTR est défini comme un pointeur sur unsigned short , tandis que wchar_t est un type natif. Vous pouvez activer ou désactiver la conformité de wchar_t avec /Zc:wchar_t .

Une chose à garder à l’esprit est que les chaînes BSTR peuvent, et le font souvent, contenir des BSTR incorporées. Un null ne signifie pas la fin de la chaîne.

Utilisez ATL et CSsortingngT, vous pouvez simplement utiliser l’opérateur d’affectation. Vous pouvez également utiliser les macros USES_CONVERSION. Celles-ci utilisent l’allocation de segment de mémoire, ce qui vous permet de ne pas perdre de mémoire.