【基於VC的ArcEngine開發】1連接數據庫

前面的話:ArcEngine是GIS巨頭企業ESRI推出的地理信息系統的二次開發包,滿足應用行業快速搭建GIS系統的需求。一般的二次開發使用C#,語言簡單,開發者可將更多的精力集中到具體的業務問題的解決,但是也有一些特殊需求,需要基於其他開發語言進行ArcEngine的二次開發。本文也是我第一次基於C++使用ArcEngine的接口連接數據庫時蒐集資料的一些彙總,希望能給以後的開發者一些方便。

文中的內容主要是基於C++的ArcEngine開發的基本環境的配置和初始化方法,實際的進一步開發中需要開發者瞭解COM的一些基礎特性,開發高級功能需要多多分析ArcEngine的接口。

一、設置導入庫


參考網址:

設置導入庫是爲了應用ArcEngine對應的庫文件,ArcEngine安裝後庫文件的路徑爲“*/Program Files/ArcGIS/com/”,庫文件的後綴是olb。導入方式是在文件下面加入以下語句。

#pragma warning (push )
#pragma warning (disable : 4192) /* Ignore warnings for types that are duplicated in win32 header files */
#pragma warning (disable : 4146) /* Ignore warnings for use of minus on unsigned types */
#pragma warning (disable : 4278) /* Ignore warnings for identifier in type library 'tlb' is already a macro */

#import "D:/Program Files/ArcGIS/com/esriSystem.olb" raw_interfaces_only, raw_native_types , no_namespace , named_guids , exclude("OLE_COLOR" , "OLE_HANDLE" , "VARTYPE" )
#import "D:/Program Files/ArcGIS/com/esriSystemUI.olb" raw_interfaces_only, raw_native_types , no_namespace , named_guids,exclude ("OLE_COLOR" ,"ICommand" ,"IProgressDialog" )
#import "D:/Program Files/ArcGIS/com/esriGeometry.olb" raw_interfaces_only, raw_native_types , no_namespace , named_guids,exclude ("OLE_COLOR" )
#import "D:/Program Files/ArcGIS/com/esriDisplay.olb" raw_interfaces_only, raw_native_types , no_namespace , named_guids,exclude ("OLE_COLOR" )
#import "D:/Program Files/ArcGIS/com/esriOutput.olb" raw_interfaces_only, raw_native_types , no_namespace , named_guids,exclude ("OLE_COLOR" )
#import "D:/Program Files/ArcGIS/com/esriGeoDatabase.olb" raw_interfaces_only, raw_native_types , no_namespace , named_guids,exclude ("OLE_COLOR" ,"ICursor" )
#import "D:/Program Files/ArcGIS/com/esriCarto.olb" raw_interfaces_only , raw_native_types, no_namespace , named_guids,exclude ("OLE_COLOR" ,"ITableDefinition" ,"UINT_PTR" )

#pragma warning (pop )

注意事項:
1、導入庫的順序按照依賴的先後順序,即被依賴庫在依賴庫之前引用。
2、如果報出接口重定義錯誤,在導入語句後加入exclude("衝突接口")。如果這種方法不能解決,需要重新命名接口,例如,報ISegment接口重定義,那麼直接在導入語句的最後加上rename(“ISegment”, “IESRISegment”),這時的接口IESRISegment就是對ISegment的重命名。
3、如果報出沒有定義接口,可能是沒有引用該接口所在的庫或引用庫的順序錯誤所致。
4、爲了避免錯誤,導入庫語句最好放在stdafx.h最後。

二、初始化AE授權

參考資料

ArcEngine針對不同的用戶發佈了不同的許可級別,用戶根據需要初始化不同的許可級別。這裏選擇的是最高的級別:esriLicenseProductCodeEngineGeoDB。

1、初始化COM庫
採用如下方式可以完成初始化,但是程序結束調用CoUninitialize()時會出現錯誤。

#if _WIN32_WINNT >= 0x0400 //對應 Windows NT 4.0
HRESULT hRes = CoInitializeEx (NULL , COINIT_MULTITHREADED );// 當前線程初始化 COM庫並設置併發模式
#else
HRESULT hRes = CoInitialize(NULL);// 以單線程的方式創建 com對象
#endif

爲了保證正確性,定義一個初始化COM的類,自動實現COM的初始化和釋放。
class ComInit
{
public:
       ComInit()
      {
#if _WIN32_WINNT >= 0x0400 //對應 Windows NT 4.0
             HRESULT hRes = CoInitializeEx (NULL , COINIT_MULTITHREADED);//當前線程初始化COM庫並設置併發模式
#else
            HRESULT hRes = CoInitialize(NULL);// 以單線程的方式初始化 COM庫
#endif
      }
      ~ ComInit()
      {
             CoUninitialize();
      }
};

2、定義AO初始化對象
IAoInitializePtr m_pAoInit ; 

3、AO初始化函數
void InitialAO ()
{     
       esriLicenseStatus  lic_status ;
       HRESULT hr;

       hr = m_pAoInit.CreateInstance (CLSID_AoInitialize );

       // 獲取是否支持讀寫許可
       m_pAoInit-> IsProductCodeAvailable(esriLicenseProductCodeEngineGeoDB ,&lic_status );

       if( lic_status == esriLicenseAvailable)
      {
             hr = m_pAoInit->Initialize (esriLicenseProductCodeEngineGeoDB ,&lic_status );
      } 
       else
      {
             // 是否支持只讀許可
             m_pAoInit-> IsProductCodeAvailable(esriLicenseProductCodeEngine ,&lic_status );
             if( lic_status == esriLicenseAvailable)
            {
                   hr = m_pAoInit->Initialize (esriLicenseProductCodeEngine ,&lic_status );
            }
      }
       if( lic_status != esriLicenseCheckedOut)
      {
             AfxMessageBox("本機沒有合適的ArcGIS授權,請與管理員聯繫!");
             return;
      }
}

4、資源釋放
void ShutDownAO (){
       // 釋放 AO
       m_pAoInit-> Shutdown();
       // 釋放 COM
       CoUninitialize();
}

注意事項:
1、COM庫或ArcEngine授權未初始化情況下會報出以下錯誤:“Microsoft C++ 異常: 內存位置 0x0012ea88 處的 _com_error

三、連接SDE數據庫


HRESULT connectToSDE (BSTR server ,
                               BSTR instance,//5151
                               BSTR user,
                               BSTR passwd,
                               BSTR database,
                               BSTR version,
                               IWorkspace ** outWorkspace)
{
       if (outWorkspace == NULL )
             return E_POINTER;

       // create the property set for the connection parameters
       IPropertySetPtr ipPropertySet ;
       HRESULT hr = ipPropertySet .CreateInstance (CLSID_PropertySet );


       // configure the propertyset
       ipPropertySet->SetProperty (CComBSTR ("SERVER" ),    CComVariant(server ));
       ipPropertySet->SetProperty (CComBSTR (L "INSTANCE"), CComVariant(instance ));
       ipPropertySet->SetProperty (CComBSTR (L "DATABASE"), CComVariant(database ));
       ipPropertySet->SetProperty (CComBSTR (L "USER"),     CComVariant(user ));
       ipPropertySet->SetProperty (CComBSTR (L "PASSWORD"), CComVariant(passwd ));
       ipPropertySet->SetProperty (CComBSTR (L "VERSION"),  CComVariant(version ));

       // open workspace
       IWorkspaceFactoryPtr ipWorkspaceFactory ;
       ipWorkspaceFactory.CreateInstance (CLSID_SdeWorkspaceFactory );
       return ipWorkspaceFactory->Open (ipPropertySet , NULL , outWorkspace);
}

四、COM編程

1、接口的定義初始化
     IDatasetNamePtr ipds_name(CLSID_FeatureDatasetName);

2、查詢接口
     IFeatureWorkspaceManagePtr ipfwsm;
     if(S_OK != m_ipworkspace->QueryInterface(&ipfwsm))
          return false;

五、附錄
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章