1. 程式人生 > >匯入型別庫注意先後順序

匯入型別庫注意先後順序

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.其實我應該在錯誤資訊中發現並推測問題的起因的,注意第二行"缺少儲存類或型別說明符",我應該在這兒就意識到是型別沒定義,但是我馬虎了.

的確,查錯也是一種進步^^,至少鍛鍊毅力shades_smile.gif

-----------------------------------------------------------------------------------------------------------------------------
                                                                                                      
                                                                                                                                                                 vigor

                                                                                                                                                               2004.12.5