c++ visual-c++ com ole bstr

c++ - Obtener un char*de_variant_t en tiempo óptimo



visual-c++ com (5)

Esto crea un temporal en la pila:

USES_CONVERSION; char *p=W2A(var.bstrVal);

Esto usa una sintaxis un poco más nueva y es probablemente más robusto. Tiene un tamaño configurable, más allá del cual usará el montón para evitar poner cadenas masivas en la pila:

char *p=CW2AEX<>(var.bstrVal);

Aquí está el código que quiero acelerar. Obtiene un valor de un conjunto de registros ADO y lo convierte en un char *. Pero esto es lento. ¿Puedo omitir la creación de _bstr_t?

_variant_t var = pRs->Fields->GetItem(i)->GetValue(); if (V_VT(&var) == VT_BSTR) { char* p = (const char*) (_bstr_t) var;


Los primeros 4 bytes del BSTR contienen la longitud. Puede recorrer y obtener todos los demás caracteres si es unicode o cada carácter si es multibyte. Algún tipo de memcpy u otro método también funcionaría. IIRC, esto puede ser más rápido que W2A o casting (LPCSTR)(_bstr_t)


Ok, mi C ++ se está poniendo un poco oxidado ... pero no creo que la conversión sea tu problema. Esa conversión realmente no hace nada, excepto decirle al compilador que considere _bstr_t un char *. Entonces solo está asignando la dirección de ese puntero a p. Nada está siendo "hecho".

¿Estás seguro de que no solo tardas mucho en obtener material de GetValue?

O mi C ++ es más rústico de lo que creo ...


Su problema (aparte de la posibilidad de una copia de memoria dentro de _bstr_t) es que está convirtiendo el UNICODE BSTR en un ANSI char *.

Puede usar las macros USES_CONVERSION que realizan la conversión en la pila, para que sean más rápidas. Alternativamente, mantenga el valor de BSTR como unicode si es posible.

para convertir:

USES_CONVERSION; char* p = strdup(OLE2A(var.bstrVal)); // ... free(p);

recuerde: la cadena devuelta por OLE2A (y sus macros hermanas) devuelve una cadena que está asignada en la pila - devuelve desde el alcance adjunto y tiene una cadena de basura a menos que la copie (y la libere con el tiempo, obviamente)


_variant_t var = pRs->Fields->GetItem(i)->GetValue();

También puede hacer que esta tarea sea más rápida evitando la recolección de campos en conjunto. Solo debe usar la colección Campos cuando necesite recuperar el elemento por nombre. Si conoce los campos por índice, puede usar esto en su lugar.

_variant_t vara = pRs->Collect[i]->Value;

Tenga en cuenta que no puedo ser un número entero ya que ADO no es compatible con VT_INTEGER, por lo que también podría utilizar una variable larga.