COM组件通用ADO访问数据库,VC中使用组件,导入组件的类型库是报错
------------------------------------------------------------------
可能这个问题对别人来说真的不是什么问题,但是要是遇上了,会被烦死掉的,所以我还是写出来,希望别人遇上的
时候能得到帮助:
I.问题概述:
我是在做一个组件的时候,用到了ADO(msado15.dll),按照常规的方法,访问数据库(SQL2000).
<1>组件方:
方法定义:
HRESULT GetRecordset([in]BSTR queryCmd,[out,retval]_Recordset **RecordsetPtr);
实现:
STDMETHODIMP CQueryRec::GetRecordset(BSTR queryCmd,_Recordset **RecordsetPtr)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
CoInitialize(NULL);
_ConnectionPtr pCon(__uuidof(Connection));
_CommandPtr pCmd(__uuidof(Command));
_RecordsetPtr pSet(__uuidof(Recordset));
pCon->Open(_T("Provider=SQLOLEDB.1;Data source=127.0.0.1;Initial Catalog=Northwind"),
_T("sa"),_T(""),adOpenUnspecified);
pCmd->ActiveConnection=pCon;
CString command(queryCmd);
pCmd->CommandText=command.operator LPCTSTR();
pSet->PutRefSource(pCmd);
pSet->CursorLocation=adUseClient;
_variant_t vNull(DISP_E_PARAMNOTFOUND,VT_ERROR);
pSet->Open(vNull,vNull,adOpenDynamic,adLockOptimistic,adCmdText);
pSet->QueryInterface(__uuidof(_Recordset),(void**)RecordsetPtr);
CoUninitialize();
return S_OK;
}
<2>vc客户端:
1.在vc客户端使用组件都先要导入组件的类型库,所以我也按常规的导入了类型库
#import "GetRec.tlb"
using namespace GETRECLib;
2.然后我也想到了,组件返回的类型里有_RecordsetPtr类型的智能指针,我于是有导入了msado15.dll
#import "msado15.dll" no_namespace rename("EOF","EndOfFile")
II.错误信息:
做完上面之后,我加入了使用组件的方法,万事大吉,开工了,开始编译,错误如下:
...: error C2146: 语法错误 : 缺少“;”(在标识符“GetRecordset”的前面)
...: error C2501: “GETRECLib::IQueryRec::_RecordsetPtr” : 缺少存储类或类型说明符
...: warning C4183: “GetRecordset”: 缺少返回类型;假定为返回“int”的成员函数
...: error C2143: 语法错误 : 缺少“;”(在“GETRECLib::IQueryRec::GetRecordset”的前面)
...: error C2433: “_RecordsetPtr” : 不允许在数据声明中使用“inline”
...: error C2501: “_RecordsetPtr” : 缺少存储类或类型说明符
...: error C2064: 项不会计算为接受 2 个参数的函数
我检查了很多遍,都没其他的问题,怎么问题老是这样呢,郁闷哦,主要是这问题的错误不好查,提示就是缺";"什么的,就是语法错误,可是没语法错误,我这点还是肯定的,因为我就只在一个新的工程里写上#import "GetRec.tlb"就错了,更让我迷惑的是用VB调用这组件没问题,正常,这下我可真不知道怎么好,因为这问题不想其他的,我还可以凭平时的一点点经验查错,这我确实没法了,我也开始以为是VC的一个bug.
IIV.问题解决:
过了三四天了,我没事就拿这代码来琢磨琢磨,终于在无意中发现是自己犯了个不注意的错误,“导入库的顺序”
我在vc客户端的StdAfx.h中:
1.#import "GetRec.tlb"
2.#import "msado15.dll" no_namespace rename("EOF","EndOfFile")
vc编译器生成的"GetRec.tlh",也就是组件的头文件,里面就有_RecordsetPtr,但是在这个VC客户端里面不能识别这种类型,的确,我是在第二步导入了"msado15.dll"但是,在这之前,头文件的定义里却不能识别,编译器对一个文件的编译都上自顶向下的,所以不认识_RecordsetPtr,于是我换了导入的先后顺序,Ok,no problem!
IV.经验教训:
1.编译器对源文件的编译都有自顶向下的先后顺序,定义要放前面,也就是想上面那种问题,要先定义类型,才能识别使用。
2.其实我应该在错误信息中发现并推测问题的起因的,注意第二行"缺少存储类或类型说明符",我应该在这儿就意识到是类型没定义,但是我马虎了.
的确,查错也是一种进步^^,至少锻炼毅力
-----------------------------------------------------------------------------------------------------------------------------
vigor
2004.12.5