Tengo un objeto BSTR que me gustaría convertir para copiar a un objeto wchar__t. Lo complicado es que la longitud del objeto BSTR puede ser de unos pocos kilobytes a unos pocos cientos de kilobytes. ¿Existe una forma eficiente de copiar los datos? Sé que podría simplemente declarar una matriz wchar_t y siempre asignar la máxima cantidad posible de datos que alguna vez necesitaría contener. Sin embargo, esto significaría asignar cientos de kilobytes de datos para algo que posiblemente solo requiera unos pocos kilobytes. ¿Alguna sugerencia?¿Cómo se puede copiar eficientemente BSTR a wchar_t []?
Respuesta
Los objetos BSTR contienen un prefijo de longitud, por lo que encontrar la longitud es barato. Averigüe la longitud, asigne una nueva matriz lo suficientemente grande como para contener el resultado, procese en eso y recuerde liberarlo cuando haya terminado.
Use ATL, y CStringT luego puede simplemente usar el operador de asignación. O puede usar las macros USES_CONVERSION, estas usan la asignación de montón, por lo que estará seguro de no perder memoria.
Nunca hay necesidad de conversión. Un puntero BSTR
apunta al primer carácter de la cadena y termina en nulo. La longitud se almacena antes del primer carácter en la memoria. BSTR
s siempre son Unicode (UTF-16/UCS-2). Hubo en un momento algo llamado 'ANSI BSTR' - hay algunas referencias en API heredadas - pero puede ignorarlas en el desarrollo actual.
Esto significa que puede pasar un BSTR
de forma segura a cualquier función esperando un wchar_t
.
En Visual Studio 2008 puede obtener un error de compilación, porque BSTR
se define como un puntero a unsigned short
, mientras que wchar_t
es un tipo nativo. Puede activar o desactivar el wchar_t
según /Zc:wchar_t
.
Una cosa a tener en cuenta es que las cadenas BSTR
pueden, y a menudo lo hacen, contener nulos incorporados. Un nulo no significa el final de la cadena.
En primer lugar, es posible que en realidad no tenga que hacer nada en absoluto, si todo lo que tiene que hacer es leer el contenido. Un tipo BSTR es un puntero a una matriz wchar_t terminada en nulo ya. De hecho, si usted comprueba las cabeceras, se encuentra que BSTR se define esencialmente como:
typedef BSTR wchar_t*;
Por lo tanto, el compilador no puede distinguir entre ellos, a pesar de que tienen una semántica diferente.
Hay dos advertencias importantes.
Se supone que los BSTR son inmutables. Nunca debe cambiar el contenido de un BSTR después de que se haya inicializado. Si lo "cambia", debe crear uno nuevo, asigne el nuevo y suelte el anterior (si es el propietario).
[ACTUALIZACIÓN: esto no es cierto; ¡lo siento! Puede modificar los BSTR en su lugar; Pocas veces he tenido la necesidad.]BSTR pueden contener caracteres nulos incorporados, mientras que las cadenas tradicionales C/C++ no lo son.
Si usted tiene una buena cantidad de control de la fuente de la BSTR, y se puede garantizar que el BSTR no tiene valores NULL incrustados, se puede leer desde el BSTR como si fuera un wchar_t y utilizar cuerdas convencionales métodos (wcscpy, etc.) para acceder a él. Si no, tu vida se vuelve más difícil. Deberá manipular siempre sus datos como más BSTR o como una matriz de wchar_t asignada dinámicamente. La mayoría de las funciones relacionadas con cadenas no funcionarán correctamente.
Supongamos que usted controla sus datos, o no se preocupe por NULL. Supongamos también que realmente necesita hacer una copia y no puede simplemente leer el BSTR existente directamente. En ese caso, se puede hacer algo como esto:
UINT length = SysStringLen(myBstr); // Ask COM for the size of the BSTR
wchar_t *myString = new wchar_t[lenght+1]; // Note: SysStringLen doesn't
// include the space needed for the NULL
wcscpy(myString, myBstr); // Or your favorite safer string function
// ...
delete myString; // Done
Si está utilizando contenedores de clase para su BSTR, la envoltura debe tener una manera de llamar SysStringLen() para usted. Por ejemplo:
CComBString use .Length();
_bstr_t use .length();
ACTUALIZACIÓN: Este es un buen artículo sobre el tema por alguien mucho más conocimiento que yo:
"Eric [Lippert]'s Complete Guide To BSTR Semantics"
ACTUALIZACIÓN: se ha sustituido strcpy() con wcscpy() en ejemplo
AFAIK, BSTRs * no * se supone que son inmutables. Es por eso que no están declarados const *. – Constantin
Hmmm ... No puedo encontrar ninguna referencia que respalde mi posición. ¿Qué estaba pensando? Voy a corregir eso. –
¿no debería usar wcscpy en lugar de strcpy? – arolson101
- 1. C++: ¿Convierte wchar_t * en BSTR?
- 2. análisis de código estático para detectar pasando un wchar_t * a BSTR
- 3. Cómo convertir char * a BSTR?
- 4. ¿Se puede copiar UIView?
- 5. Convierte BSTR a char *
- 6. Cómo convierto jstring a wchar_t *
- 7. ¿Cómo convierto wchar_t * a std :: string? .?
- 8. QChar a wchar_t
- 9. convertido BSTR a const char *
- 10. Cómo convertir wchar_t * a const char *
- 11. ¿A quién pertenece BSTR devuelto?
- 12. ¿Puedes lanzar un LPTSTR a un BSTR?
- 13. C++ No se puede copiar, excepto a veces
- 14. UIPasteboard - no se puede copiar el texto
- 15. no se puede convertir 'LPCWSTR {aka const wchar_t *}' a 'LPCSTR {aka const char *}
- 16. ¿Cómo se puede copiar/pegar desde el portapapeles en C++?
- 17. ¿Se requiere conversión endian para datos wchar_t?
- 18. wchar_t puntero
- 19. COM, VARIANT que contiene BSTR. ¿Quién asigna?
- 20. wchar_t y codificación
- 21. ¿Cuál es el significado de BSTR, LPCOLESTR y otros?
- 22. char vs wchar_t
- 23. cómo convertir la matriz de caracteres a wchar_t array?
- 24. Convierte wchar_t en int
- 25. wchar_t vs wint_t
- 26. No se puede copiar el archivo en archivo dSYM
- 27. eficientemente ordenar un IList <T> sin copiar la lista de fuentes
- 28. ¿se puede copiar la firma del certificado digital? (ssl)
- 29. Cómo usar std :: atomic eficientemente
- 30. Wchar_t portátil en C++
wchar_t no está garantizado para ser exactamente del tamaño de un corto. – ben
Creo que esta operación siempre es segura, pero no siempre da los resultados esperados. Un BSTR puede contener caracteres nulos en su cuerpo (de ahí el prefijo de longitud), mientras que una función que espera un wchar_t * interpretará el primer carácter nulo como el final de la cadena. – Martin
No se puede "pasar un BSTR de forma segura a cualquier función esperando un wchar_t *". Compara SysStringLen (NULL) y wcslen (NULL). – Constantin