在最佳时间内从_variant_t获取char *

时间:2020-03-06 14:34:01  来源:igfitidea点击:

这是我要加速的代码。它从ADO记录集中获取一个值并将其转换为char *。但这很慢。我可以跳过_bstr_t的创建吗?

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

                if (V_VT(&var) == VT_BSTR)
                {
                    char* p = (const char*) (_bstr_t) var;

解决方案

这会在堆栈上创建一个临时文件:

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

这使用了较新的语法,并且可能更健壮。它具有可配置的大小,超过该大小将使用堆,从而避免将大量字符串放入堆栈:

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

问题(除了在_bstr_t内进行内存复制的可能性外)是我们要将UNICODE BSTR转换为ANSI char *。

我们可以使用USES_CONVERSION宏在堆栈上执行转换,因此它们可能会更快。或者,如果可能,将BSTR值保留为unicode。

转换:

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

// ...

free(p);

请记住,从OLE2A返回的字符串(及其姐妹宏)返回了一个从堆栈范围返回的在堆栈上分配的字符串,除非我们将其复制(并且最终将其释放,否则显然是垃圾字符串),否则我们将获得垃圾字符串

好的,我的C ++有点生锈了...但是我不认为转换是问题。除了告诉编译器将_bstr_t视为char *外,该转换实际上没有任何作用。然后,我们只需将指针的地址分配给p。实际上什么都没有"完成"。

我们确定从GetValue获取信息不仅缓慢吗?

还是我的C ++比我想象的要生锈...

BSTR的前4个字节包含长度。我们可以遍历并获取所有其他字符(如果是unicode)或者获取每个字符(如果是多字节)。某种memcpy或者其他方法也可以工作。 IIRC,这可能比W2A或者强制转换(LPCSTR)(_ bstr_t)更快。

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

我们也可以通过完全避免字段集合来加快分配速度。仅在需要按名称检索项目时才应使用Fields集合。如果我们知道按索引显示的字段,则可以使用它。

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

注意我不能是整数,因为ADO不支持VT_INTEGER,因此我们最好使用long变量。