Ottenere un carattere * da un _variant_t in tempo ottimale
-
02-07-2019 - |
Domanda
Ecco il codice che voglio velocizzare. Sta ottenendo un valore da un recordset ADO e convertendolo in un carattere *. Ma questo è lento. Posso saltare la creazione di _bstr_t?
_variant_t var = pRs->Fields->GetItem(i)->GetValue();
if (V_VT(&var) == VT_BSTR)
{
char* p = (const char*) (_bstr_t) var;
Soluzione
I primi 4 byte del BSTR contengono la lunghezza. È possibile eseguire il ciclo continuo e ottenere tutti gli altri personaggi se Unicode o tutti i personaggi se multibyte. Funzionerebbe anche una sorta di memcpy o altri metodi. IIRC, questo può essere più veloce di W2A
o lanciare (LPCSTR)(_bstr_t)
Altri suggerimenti
Il tuo problema (oltre alla possibilità di una copia di memoria all'interno di _bstr_t) è che stai convertendo UNICODE BSTR in un carattere ANSI *.
Puoi utilizzare le macro USES_CONVERSION che eseguono la conversione nello stack, quindi potrebbero essere più veloci. In alternativa, mantenere il valore BSTR come unicode, se possibile.
per convertire:
USES_CONVERSION;
char* p = strdup(OLE2A(var.bstrVal));
// ...
free(p);
ricorda - la stringa restituita da OLE2A (e le sue macro gemelle) restituiscono una stringa che è allocata nello stack - ritorna dall'ambito che racchiude e hai una stringa di immondizia a meno che non la copi (e alla fine, ovviamente, ovviamente)
Questo crea un temporaneo nello stack:
USES_CONVERSION;
char *p=W2A(var.bstrVal);
Questo utilizza una sintassi leggermente più recente ed è probabilmente più robusto. Ha una dimensione configurabile, oltre la quale utilizzerà l'heap in modo da evitare di mettere enormi stringhe nello stack:
char *p=CW2AEX<>(var.bstrVal);
_variant_t var = pRs->Fields->GetItem(i)->GetValue();
Puoi anche rendere questo compito più veloce evitando la raccolta dei campi tutti insieme. Utilizzare la raccolta Campi solo quando è necessario recuperare l'elemento per nome. Se conosci i campi per indice, puoi invece utilizzare questo.
_variant_t vara = pRs->Collect[i]->Value;
Nota che non posso essere un numero intero poiché ADO non supporta VT_INTEGER, quindi potresti anche utilizzare una variabile lunga.
Ok, il mio C ++ sta diventando un po 'arrugginito ... ma non credo che la conversione sia un tuo problema. Quella conversione in realtà non fa altro che dire al compilatore di considerare _bstr_t un carattere *. Quindi stai solo assegnando l'indirizzo di quel puntatore a p. In realtà non viene fatto nulla "quot."
Sei sicuro che non sia solo lento ottenere cose da GetValue?
O il mio C ++ è più pericoloso di quanto penso ...