Question

Here's the code I want to speed up. It's getting a value from an ADO recordset and converting it to a char*. But this is slow. Can I skip the creation of the _bstr_t?

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

                if (V_VT(&var) == VT_BSTR)
                {
                    char* p = (const char*) (_bstr_t) var;
Was it helpful?

Solution

The first 4 bytes of the BSTR contain the length. You can loop through and get every other character if unicode or every character if multibyte. Some sort of memcpy or other method would work too. IIRC, this can be faster than W2A or casting (LPCSTR)(_bstr_t)

OTHER TIPS

Your problem (other than the possibility of a memory copy inside _bstr_t) is that you're converting the UNICODE BSTR into an ANSI char*.

You can use the USES_CONVERSION macros which perform the conversion on the stack, so they might be faster. Alternatively, keep the BSTR value as unicode if possible.

to convert:

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

// ...

free(p);

remember - the string returned from OLE2A (and its sister macros) return a string that is allocated on the stack - return from the enclosing scope and you have garbage string unless you copy it (and free it eventually, obviously)

This creates a temporary on the stack:

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

This uses a slightly newer syntax and is probably more robust. It has a configurable size, beyond which it will use the heap so it avoids putting massive strings onto the stack:

char *p=CW2AEX<>(var.bstrVal);
_variant_t var = pRs->Fields->GetItem(i)->GetValue(); 

You can also make this assignment quicker by avoiding the fields collection all together. You should only use the Fields collection when you need to retrieve the item by name. If you know the fields by index you can instead use this.

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

Note i cannot be an integer as ADO does not support VT_INTEGER, so you might as well use a long variable.

Ok, my C++ is getting a little rusty... but I don't think the conversion is your problem. That conversion doesn't really do anything except tell the compiler to consider _bstr_t a char*. Then you're just assigning the address of that pointer to p. Nothing's actually being "done."

Are you sure it's not just slow getting stuff from GetValue?

Or is my C++ rustier than I think...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top