VARIANT 和 BSTR 是如何互相转换?

coolstar 2002-07-22 08:45:54
VARIANT 和 BSTR 是如何互相转换?
...全文
242 7 打赏 收藏 举报
写回复
7 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
coolstar 2002-07-22
问题已解决
if (varValue.vt && VT_BSTR) {
*strSQL= SysAllocString(*(varValue.pbstrVal));
}
  • 打赏
  • 举报
回复
coolstar 2002-07-22
上面的代码中
*strSQL= ::SysAllocString(T2OLE(varValue.vt));
编译通不过

  • 打赏
  • 举报
回复
coolstar 2002-07-22
STDMETHODIMP Cgetsql::getSQL(BSTR strXML, BSTR *strSQL)
{
// TODO: Add your implementation code here

HRESULT hr;
IXMLDOMDocument *pXMLDoc;
IXMLDOMNode * pXDN;
IXMLDOMElement *pIXMLDOMElement = NULL;
VARIANT varValue;
USES_CONVERSION;

BSTR bstrAttributeName = ::SysAllocString(L"test");

VARIANT_BOOL * isSuccessful=false;
//...
hr = CoInitialize(NULL);
// 得到关于IXMLDOMDocument接口的指针pXMLDOC
hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument, (void**)&pXMLDoc);
// 得到关于IXMLDOMNode接口的指针pXDN
hr = pXMLDoc->QueryInterface(IID_IXMLDOMNode, (void **)&pXDN);
// Check the return value.
pXMLDoc->loadXML(strXML,isSuccessful);

//pXMLDoc->get_xml(strSQL);

hr = pXMLDoc->get_documentElement(&pIXMLDOMElement);
hr = pIXMLDOMElement->getAttribute(bstrAttributeName, &varValue);

*strSQL= ::SysAllocString(T2OLE(varValue.vt)); ??? 这一行应该怎么写?


SysFreeString(bstrAttributeName ); // Free previous string, if any.

pIXMLDOMElement->Release();
return S_OK;
}
  • 打赏
  • 举报
回复
尘雨 2002-07-22
ADO的官方说明
带了两个例子
很有价值哦

ADO VC++ Extensions 可将 Recordset 对象的字段映射到 C/C++ 变量,对字段与变量之间映射关系的定义称为“绑定条目”。预处理宏用来定义数值、定长和变长变量的绑定条目。

将 BEGIN_ADO_BINDING 和 END_ADO_BINDING 宏之间的绑定条目用括号括起。不要在绑定条目结尾使用逗号或分号,这些定界符仅限在宏中使用。

为每个将被转换为 C/C++ 变量的字段指定一个绑定条目。使用适当的 ADO_FIXED_LENGTH_BINDING_ENTRY、ADO_NUMERIC_BINDING_ENTRY 或 ADO_VARIABLE_LENGTH_BINDING_ENTRY 宏。

在宏的参数中,用序数指定将被提出的 Recordset 字段 — 0 标识第一字段,1 标识第二字段,依此类推。

使用数据类型声明 C/C++ 变量。如果变量为数值,也可指定精度和范围。如果变量为变长变量(如字符串),则必须以字节指定变量的最大尺寸。如果需要,Recordset 字段值可被强制为该数据类型。

指定临时的工作缓冲区,用来将字段值从 VARIANT 转换为 C/C++ 变量。缓冲区应至少与此 C/C++ 变量一样大。

将布尔型修改参数设置为 TRUE 使 ADO 可更新绑定的字段,如只检查字段而不将其更改,可设置为 FALSE。VC++ Extensions 不保留有关字段的状态信息,因此必须指定 ADO 是否更改字段值(例如,由数据源保留的自动增值字段的值)。因此该字段的修改参数应设置为 FALSE。

状态参数可告诉您从 Recordset 字段到 C 或 C++ 变量的转换是否成功以及变量的内容是否有效。该参数的两个最重要的值是 adFldOK (意味着转换成功)和 adFldNull (意味着字段是 NULL—无值可供转换)。

首先检测该参数以决定 C 或 C++ 变量是否有效。例如,如果字段具有有效的行内容,状态将会是 adFldOK;如果移动到另一个字段为 NULL 的行,状态则将是 adFldNull。然而,C 或 C++ 变量的内容将不被更改 — 该变量将仍然包含上一行的字段值。

将 Recordset 绑定到变量

在应用程序中,调用 BindToRecordset 接口方法可使 Recordset 字段关联(或绑定)到 C/C++ 变量,无论何时更改 Recordset 对象的当前行,C/C++ 变量都将自动更新。

头文件

要使用 VC++ Extensions,请在应用程序中包含如下文件:

#include <icrsint.h>
接口方法

IADORecordBinding 接口具有使 Recordset 字段与 C/C++ 变量关联、添加新行和执行更新的方法。所有这三个方法都可使指针指向由 CADORecordBinding 派生的类,该 CADORecordBinding 定义每个字段和变量之间的绑定。

接口方法是:

BindToRecordset(&binding)
调用该方法可使变量与字段相关联。

AddNew(&binding)
调用该方法可间接调用 ADO AddNew 方法。

Update(&binding)
调用该方法可间接调用 ADO Update 方法。

预处理宏

BEGIN_ADO_BINDING(cls)


ADO_FIXED_LENGTH_BINDING_ENTRY(Ordinal, DataType, Buffer, Status, Modify)


ADO_NUMERIC_BINDING_ENTRY(Ordinal, DataType, Buffer, Precision, Scale,
Status, Modify)


ADO_VARIABLE_LENGTH_BINDING_ENTRY(Ordinal, DataType, Buffer, Size,
Status, Modify)


END_ADO_BINDING()

参数 说明
cls 类,定义绑定条目,缓冲区,和 Recordset 对象。
Ordinal 按顺序的字段号码,0 标识第一字段,1 标识第二字段,依此类推。
DataType 储存已转换字段的变量的数据类型。
Buffer 缓冲区,用于将字段转换为变量。
Status 指示字段转换是否成功。
Modify 布尔标志;如果为 TRUE,则表明 ADO 可以更新关联的字段。
Precision 在数值变量中可被表现出的数字位数。
Scale 位于数值变量中的小数点后的位数。
Size 变长变量所需的字节数,诸如:字符串。




状态参数值 说明
adFldOK 返回非 NULL 字段值。
adFldBadAccessor 绑定无效。
adFldCantConvertValue 由于符号不匹配和数据溢出以外的原因,值不能转换。
adFldNull 返回 NULL。
adFldTruncated 变长数据或数值型数字被截短。
adFldSignMismatch 值有符号,而变量数据类型无符号。
adFldDataOverFlow 值大于在变量数据类型中的存储大小。
adFldCantCreate 已打开未知列类型和字段。
adFldUnavailable 无法确定字段值 — 例如在无默认值的新建、未指定的字段中。
adFldPermissionDenied 更新时,不允许写入数据。
adFldIntegrityViolation 更新时,字段值将破坏列的完整性。
adFldSchemaViolation 更新时,字段值将破坏列模式。
adFldBadStatus 更新时,无效的状态参数。
adFldDefault 更新时,使用了默认值。


范例: 无 Extensions 的 ADO


该程序段说明了如何从字段检索数值并将数值转换为 C++ 变量。

#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>

Class CEmployee
{
public:
FetchEmployeeData();

char m_szFirstName[30];
char m_szLastName[30];
int nAge;
};

CEmployee::FetchEmployeeData()
{
_ConnectionPtr pCon();
_RecordsetPtr pRs();
FieldPtr pfldFirstName, pfldLastName, pfldAge;
_variant_t vFirstName, vLastName, vAge;

pCon.CreateInstance(__uuidof(Connection));
pCon->Open("pubs", "sa", "");

pRs.CreateInstance(__uuidof(Recordset));
pRs->Open("select FirstName, LastName, Age from Employees", pCon,
adOpenForwardOnly, adLockReadOnly, adCmdUnknown);

pfldFirstName = pRs->Fields->GetItem(0);
pfldLastName = pRs->Fields->GetItem(1);
pfldAge = pRs->Fields->GetItem(2);

while (VARIANT_FALSE == pRs->EndOfFile)
{
vFirstName.Clear();
vLastName.Clear();
vAge.Clear();

vFirstName = pfldFirstName->Value;
WideCharToMultiByte(CP_ACP, 0, vFirstName.bstrVal, -1,
m_szFirstName, sizeof(m_szFirstName), NULL, NULL);

vLastName = pfldLastName->Value;
WideCharToMultiByte(CP_ACP, 0, vLastName.bstrVal, -1,
m_szLastName, sizeof(m_szLastName), NULL, NULL);

nAge = vAge.iVal;

pRs->MoveNext();
}
}

范例: 带 Extensions 的 ADO


该程序说明了如何从字段检索数值并将数值转换为 C++ 变量。它包括了在程序段(范例:无 Extensions 的 ADO)中所描述的功能。


#define INITGUID
#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>
#include "icrsint.h"

void dump_com_error(_com_error &e)
{
printf("Error\n");
printf("\a\tCode = %08lx\n", e.Error());
printf("\a\tCode meaning = %s", e.ErrorMessage());
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
}

class CCustomRs :
public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
ADO_VARIABLE_LENGTH_BINDING_ENTRY(1, adVarChar, m_szau_lname,
sizeof(m_szau_lname), lau_lnameStatus, FALSE)
ADO_VARIABLE_LENGTH_BINDING_ENTRY(2, adVarChar, m_szau_fname,
sizeof(m_szau_fname), lau_fnameStatus, TRUE)
END_ADO_BINDING()

public:
CHAR m_szau_lname[41];
ULONG lau_lnameStatus;
CHAR m_szau_fname[41];
ULONG lau_fnameStatus;
};

VOID main()
{
HRESULT hr;
IADORecordBinding *picRs = NULL;

::CoInitialize(NULL);

try
{
_RecordsetPtr pRs.CreateInstance(__uuidof(Recordset)); CCustomRs rs;

pRs->Open("select FirstName, LastName, Age from Employees",
"dsn=pubs;uid=sa;pwd=;",
adOpenStatic, adLockOptimistic, adCmdUnknown);

if (FAILED(hr = pRs->QueryInterface(__uuidof(IADORecordBinding),
(LPVOID*)&picRs)))
_com_issue_error(hr);

if (FAILED(hr = picRs->BindToRecordset(&rs)))
_com_issue_error(hr);

while (VARIANT_FALSE == pRs->EndOfFile)
{
// 处理 CCustomRs C++ 实例变量中的数据。

printf("\a\tName = %s \t%s",
(lau_fnameStatus == adFldOK ? m_szau_fname : "<NULL>"),
(lau_lnameStatus == adFldOK ? m_szau_lname): "<NULL>"));

// 更改 Recordset 的当前行。
// 新当前行的 Recordset 数据将被
// 自动取出并防止在 CCustomRs C++ 实例变量中。

pRs->MoveNext();
}
}
catch (_com_error &e)
{
dump_com_error(e);
}

if (picRs)
picRs->Release();

CoUninitialize();
};



  • 打赏
  • 举报
回复
尘雨 2002-07-22
ADO的官方说明
带了两个例子
很有价值哦

ADO VC++ Extensions 可将 Recordset 对象的字段映射到 C/C++ 变量,对字段与变量之间映射关系的定义称为“绑定条目”。预处理宏用来定义数值、定长和变长变量的绑定条目。

将 BEGIN_ADO_BINDING 和 END_ADO_BINDING 宏之间的绑定条目用括号括起。不要在绑定条目结尾使用逗号或分号,这些定界符仅限在宏中使用。

为每个将被转换为 C/C++ 变量的字段指定一个绑定条目。使用适当的 ADO_FIXED_LENGTH_BINDING_ENTRY、ADO_NUMERIC_BINDING_ENTRY 或 ADO_VARIABLE_LENGTH_BINDING_ENTRY 宏。

在宏的参数中,用序数指定将被提出的 Recordset 字段 — 0 标识第一字段,1 标识第二字段,依此类推。

使用数据类型声明 C/C++ 变量。如果变量为数值,也可指定精度和范围。如果变量为变长变量(如字符串),则必须以字节指定变量的最大尺寸。如果需要,Recordset 字段值可被强制为该数据类型。

指定临时的工作缓冲区,用来将字段值从 VARIANT 转换为 C/C++ 变量。缓冲区应至少与此 C/C++ 变量一样大。

将布尔型修改参数设置为 TRUE 使 ADO 可更新绑定的字段,如只检查字段而不将其更改,可设置为 FALSE。VC++ Extensions 不保留有关字段的状态信息,因此必须指定 ADO 是否更改字段值(例如,由数据源保留的自动增值字段的值)。因此该字段的修改参数应设置为 FALSE。

状态参数可告诉您从 Recordset 字段到 C 或 C++ 变量的转换是否成功以及变量的内容是否有效。该参数的两个最重要的值是 adFldOK (意味着转换成功)和 adFldNull (意味着字段是 NULL—无值可供转换)。

首先检测该参数以决定 C 或 C++ 变量是否有效。例如,如果字段具有有效的行内容,状态将会是 adFldOK;如果移动到另一个字段为 NULL 的行,状态则将是 adFldNull。然而,C 或 C++ 变量的内容将不被更改 — 该变量将仍然包含上一行的字段值。

将 Recordset 绑定到变量

在应用程序中,调用 BindToRecordset 接口方法可使 Recordset 字段关联(或绑定)到 C/C++ 变量,无论何时更改 Recordset 对象的当前行,C/C++ 变量都将自动更新。

头文件

要使用 VC++ Extensions,请在应用程序中包含如下文件:

#include <icrsint.h>
接口方法

IADORecordBinding 接口具有使 Recordset 字段与 C/C++ 变量关联、添加新行和执行更新的方法。所有这三个方法都可使指针指向由 CADORecordBinding 派生的类,该 CADORecordBinding 定义每个字段和变量之间的绑定。

接口方法是:

BindToRecordset(&binding)
调用该方法可使变量与字段相关联。

AddNew(&binding)
调用该方法可间接调用 ADO AddNew 方法。

Update(&binding)
调用该方法可间接调用 ADO Update 方法。

预处理宏

BEGIN_ADO_BINDING(cls)


ADO_FIXED_LENGTH_BINDING_ENTRY(Ordinal, DataType, Buffer, Status, Modify)


ADO_NUMERIC_BINDING_ENTRY(Ordinal, DataType, Buffer, Precision, Scale,
Status, Modify)


ADO_VARIABLE_LENGTH_BINDING_ENTRY(Ordinal, DataType, Buffer, Size,
Status, Modify)


END_ADO_BINDING()

参数 说明
cls 类,定义绑定条目,缓冲区,和 Recordset 对象。
Ordinal 按顺序的字段号码,0 标识第一字段,1 标识第二字段,依此类推。
DataType 储存已转换字段的变量的数据类型。
Buffer 缓冲区,用于将字段转换为变量。
Status 指示字段转换是否成功。
Modify 布尔标志;如果为 TRUE,则表明 ADO 可以更新关联的字段。
Precision 在数值变量中可被表现出的数字位数。
Scale 位于数值变量中的小数点后的位数。
Size 变长变量所需的字节数,诸如:字符串。




状态参数值 说明
adFldOK 返回非 NULL 字段值。
adFldBadAccessor 绑定无效。
adFldCantConvertValue 由于符号不匹配和数据溢出以外的原因,值不能转换。
adFldNull 返回 NULL。
adFldTruncated 变长数据或数值型数字被截短。
adFldSignMismatch 值有符号,而变量数据类型无符号。
adFldDataOverFlow 值大于在变量数据类型中的存储大小。
adFldCantCreate 已打开未知列类型和字段。
adFldUnavailable 无法确定字段值 — 例如在无默认值的新建、未指定的字段中。
adFldPermissionDenied 更新时,不允许写入数据。
adFldIntegrityViolation 更新时,字段值将破坏列的完整性。
adFldSchemaViolation 更新时,字段值将破坏列模式。
adFldBadStatus 更新时,无效的状态参数。
adFldDefault 更新时,使用了默认值。


范例: 无 Extensions 的 ADO


该程序段说明了如何从字段检索数值并将数值转换为 C++ 变量。

#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>

Class CEmployee
{
public:
FetchEmployeeData();

char m_szFirstName[30];
char m_szLastName[30];
int nAge;
};

CEmployee::FetchEmployeeData()
{
_ConnectionPtr pCon();
_RecordsetPtr pRs();
FieldPtr pfldFirstName, pfldLastName, pfldAge;
_variant_t vFirstName, vLastName, vAge;

pCon.CreateInstance(__uuidof(Connection));
pCon->Open("pubs", "sa", "");

pRs.CreateInstance(__uuidof(Recordset));
pRs->Open("select FirstName, LastName, Age from Employees", pCon,
adOpenForwardOnly, adLockReadOnly, adCmdUnknown);

pfldFirstName = pRs->Fields->GetItem(0);
pfldLastName = pRs->Fields->GetItem(1);
pfldAge = pRs->Fields->GetItem(2);

while (VARIANT_FALSE == pRs->EndOfFile)
{
vFirstName.Clear();
vLastName.Clear();
vAge.Clear();

vFirstName = pfldFirstName->Value;
WideCharToMultiByte(CP_ACP, 0, vFirstName.bstrVal, -1,
m_szFirstName, sizeof(m_szFirstName), NULL, NULL);

vLastName = pfldLastName->Value;
WideCharToMultiByte(CP_ACP, 0, vLastName.bstrVal, -1,
m_szLastName, sizeof(m_szLastName), NULL, NULL);

nAge = vAge.iVal;

pRs->MoveNext();
}
}

范例: 带 Extensions 的 ADO


该程序说明了如何从字段检索数值并将数值转换为 C++ 变量。它包括了在程序段(范例:无 Extensions 的 ADO)中所描述的功能。


#define INITGUID
#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>
#include "icrsint.h"

void dump_com_error(_com_error &e)
{
printf("Error\n");
printf("\a\tCode = %08lx\n", e.Error());
printf("\a\tCode meaning = %s", e.ErrorMessage());
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
}

class CCustomRs :
public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
ADO_VARIABLE_LENGTH_BINDING_ENTRY(1, adVarChar, m_szau_lname,
sizeof(m_szau_lname), lau_lnameStatus, FALSE)
ADO_VARIABLE_LENGTH_BINDING_ENTRY(2, adVarChar, m_szau_fname,
sizeof(m_szau_fname), lau_fnameStatus, TRUE)
END_ADO_BINDING()

public:
CHAR m_szau_lname[41];
ULONG lau_lnameStatus;
CHAR m_szau_fname[41];
ULONG lau_fnameStatus;
};

VOID main()
{
HRESULT hr;
IADORecordBinding *picRs = NULL;

::CoInitialize(NULL);

try
{
_RecordsetPtr pRs.CreateInstance(__uuidof(Recordset)); CCustomRs rs;

pRs->Open("select FirstName, LastName, Age from Employees",
"dsn=pubs;uid=sa;pwd=;",
adOpenStatic, adLockOptimistic, adCmdUnknown);

if (FAILED(hr = pRs->QueryInterface(__uuidof(IADORecordBinding),
(LPVOID*)&picRs)))
_com_issue_error(hr);

if (FAILED(hr = picRs->BindToRecordset(&rs)))
_com_issue_error(hr);

while (VARIANT_FALSE == pRs->EndOfFile)
{
// 处理 CCustomRs C++ 实例变量中的数据。

printf("\a\tName = %s \t%s",
(lau_fnameStatus == adFldOK ? m_szau_fname : "<NULL>"),
(lau_lnameStatus == adFldOK ? m_szau_lname): "<NULL>"));

// 更改 Recordset 的当前行。
// 新当前行的 Recordset 数据将被
// 自动取出并防止在 CCustomRs C++ 实例变量中。

pRs->MoveNext();
}
}
catch (_com_error &e)
{
dump_com_error(e);
}

if (picRs)
picRs->Release();

CoUninitialize();
};



  • 打赏
  • 举报
回复
nichang 2002-07-22
_variant_t 和_bstr_t更方便一些
  • 打赏
  • 举报
回复
nichang 2002-07-22
用_variant_t 和_bstr_t更方便一些
  • 打赏
  • 举报
回复
发帖
VC/MFC

1.6w+

社区成员

VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
帖子事件
创建了帖子
2002-07-22 08:45
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……