Programming Arc Objects with VC Copyright 2002 ESRI
Programming Arc. Objects with VC++ Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++)
Lesson 2 overview u VC++ and Arc. Objects/COM programming review u How to import type libraries u Smart pointers u COM data types, HRESULTs, strings, and variants u Microsoft Visual Studio u Exercise 2: Simple console application Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 2
How VC++ facilitates Arc. Objects development u Client-side COM support u Native compiler support: Direct-To-COM (DTC) u #import u Support u directive to import type libraries classes for standard OLE types (BSTRs, VARIANTs, …) Server-side COM support u ATL (Active Template Library) u Templates and wizards for building COM objects and servers Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 3
Importing the Arc. Objects library u #import modifiers are required // stdafx. h u #pragma warning(push) // Sets the current warning state #pragma warning(disable : 4146) // Ignore – 2147483648 for uint #pragma warning(disable : 4192) // Exclude‘name’ while importing #import "c: arcgisarcexe 81binesri. Core. olb" // Type lib to generate C++ mapping raw_interfaces_only, // Don’t add raw_ to method names raw_native_types, // Don’t map to DTC smart types no_namespace, // Don’t wrap with C++ name space named_guids, // Named guids and declspecs exclude("OLE_COLOR", "OLE_HANDLE") // Exclude conflicting types #pragma warning(pop) // Restores state of warnings – undo Specify esri. Core. olb path: Tools > Options > Directories Instructor Demo Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 4
Arc. Objects wrapper classes u #import automatically generates type library wrappers u Creates typedefs, smart pointers, structures… // Created by Microsoft (R) C/C++ Compiler Version 12. 00. 8168. 0 (d 727 fb 44). // // c: studentarcobjectscppexercises(1) - cppaoconsoleapp_solutiondebugesri. Core. tlh // // C++ source equivalent of Win 32 type library esri. Core. olb // compiler-generated file created 12/20/01 at 11: 33: 49 - DO NOT EDIT! … /* interface */ IMap; struct __declspec(uuid("34 b 2 ef 81 -f 4 ac-11 d 1 -a 245 -080009 b 6 f 22 b")) … extern "C" const GUID __declspec(selectany) CLSID_Map = {0 xe 6 bdaa 76, 0 x 4 d 35, 0 x 11 d 0, {0 x 98, 0 xbe, 0 x 00, 0 x 80, 0 x 5 f, 0 x 7 c, 0 xed, 0 x 21}}; … _COM_SMARTPTR_TYPEDEF(IMap, __uuidof(IMap)); Typedef _com_ptr_t<_com_IIID<IMap, __uuidof(IMap)>> IMap. Ptr; … struct __declspec(uuid("e 6 bdaa 75 -4 d 35 -11 d 0 -98 be-00805 f 7 ced 21")) IMap : IUnknown { // Raw methods provided by interface virtual HRESULT __stdcall get_Name ( BSTR * Name ) = 0; virtual HRESULT __stdcall put_Name ( BSTR Name ) = 0; … Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 5
DTC smart types u VC++ classes that encapsulate data types Encapsulates a COM interface pointer (smart u _com_ptr_t<> pointer) u _bstr_t u _variant_t initializes Encapsulates variant type and automatically u _com_error Represents a COM exception using IError. Info Encapsulates the BSTR data type u Classes behave like raw types u Helpful constructors, functions, and operators u Maps all COM errors to C++ exceptions u Use to simplify Arc. Objects code… Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 6
Initializing the COM library u Necessary for stand-alone Arc. Objects applications u Steps 1. : : Co. Initialize() - Loads the COM libraries 2. Cocreate and use Arc. Objects objects 3. : : Co. Uninitialize() - Unloads COM libraries #include "stdafx. h" int main(int argc, char* argv[]) { : : Co. Initialize(NULL); IMap. Ptr ip. Map(CLSID_Map); // Simple code to create and call COM objects int i. Layers; ip. Map->get_Layer. Count(&i. Layers); _tprint(“Number of layers: %i n“, i. Layers); : : Co. Uninitialize(); } Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 7
Creating new Arc. Objects objects u COM API – : : Co. Create. Instance() // Co. Create a Map IMap* p. Map; HRESULT hr = : : Co. Create. Instance( CLSID_Map, 0, CLSCTX_ALL, IID_IMap, (void **) &p. Map ); if (FAILED(hr)) return hr; u // Class identifier (CLSID) of the object // Pointer to outer unknown pointer // Context for running executable code // Reference to the interface identifier // Indirect pointer to requested interface // Check HRESULT… DTC smart pointers – Simplified but less control… // Co. Create a Map IMap. Ptr ip. Map(CLSID_Map); if (ip. Map == NULL) return E_POINTER; Copyright © 2002 ESRI. All rights reserved. // Check for NULL Advanced Arc. Objects Component Development II (C++) 8
Querying interfaces u COM API – IUnknown: : Query. Interface() // Co. Create a Map IMap* p. IMap; : : Co. Create. Instance(CLSID_Map, 0, CLSCTX_ALL, IID_IMap, (void **) &p. Map); IActive. View* p. Active. View; p. Map->Query. Interface(IID_IActive. View, (void **) &p. Active. View); // QI u DTC smart pointers – Use assignment operator // Co. Create a Map IMap. Ptr ip. Map(CLSID_Map); // QI IActive. View. Ptr ip. Active. View(ip. Map); // QI // or use the assignment “=“ operator directly IActive. View. Ptr ip. Active. View; ip. Active. View = ip. Map; Copyright © 2002 ESRI. All rights reserved. // QI Advanced Arc. Objects Component Development II (C++) 9
Object lifetime control: Smart pointers // Smart pointer reference count test long ref. Count; // Co. Create the Simple. Object IUnknown. Ptr ip. Unk(CLSID_Simple. Object); // Add. Ref ISimple. Object. Ptr ip. Magic(ip. Unk); // Add. Ref ip. Magic->get_Reference. Count(&ref. Count); IAnother. Interface. Ptr ip. Magic 2(ip. Magic); // Add. Ref ip. Magic->get_Reference. Count(&ref. Count); ip. Magic 2 = NULL; // What happens? ip. Magic->get_Reference. Count(&ref. Count); ip. Magic = NULL; // What happens? // What happens to ip. Unk here? : : Co. Create. Instance(CLSID_Simple. Object, 0, CLSCTX_ALL, IID_IUnknown, (void **) &ip. Unk); ip. Unk = NULL; Instructor Demo Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 10
COM data type mapping Language IDL Microsoft C++ Visual Basic Microsoft Java Boolean unsigned char unsupported char byte unsigned char unsupported char small char unsupported char short Integer short long Long int Base hyper __int 64 unsupported long Types float Single float double Double double char unsigned char unsupported char wchar_t Integer short enum Enum int Interface Pointer Interface Ref. Extended VARIANT Variant ms. com. Variant Types BSTR String java. lang. String Boolean [true/false] VARIANT_BOOL short (-1 true/0 false) Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 11
BSTRs u COM API – Sys. Alloc. String, Sys. String. Len, Sys. Free. String int main(int argc, char* argv[]) { BSTR bstr. DBPath = : : Sys. Alloc. String(L". . \Data\US. mdb"); BSTR bstr. FCName = : : Sys. Alloc. String(L"States"); IFeature. Class. Ptr ip. Feature. Class; Select. Feature. Class 1(bstr. DBPath, bstr. FCName, &ip. Feature. Class); : : Sys. Free. String(bstr. DBPath); : : Sys. Free. String(bstr. FCName); } u DTC smart type – _bstr_t int main(int argc, char* argv[]) { _bstr_t bstr. DBPath(L". . \Data\US. mdb"); _bstr_t bstr. FCName(L"States"); IFeature. Class. Ptr ip. Feature. Class; Select. Feature. Class 1(bstr. DBPath, bstr. FCName, &ip. Feature. Class); } Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 12
VARIANTs u COM API – Variant. Init() and Variant. Clear() long l = 1000; VARIANT v. Value 1; : : Variant. Init(&v. Value 1); v. Value 1. vt = VT_R 4; v. Value 1. l. Val = l; printf("The value is: %dn", v. Value 1. l. Val); // Set variant type here : : Variant. Clear(&v. Value 1); u DTC smart type – _variant_t long l = 1000; _variant_t v. Value 2(l); printf("The value is: %dn", v. Value 2. l. Val); Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 13
Not so smart types u Understand the behavior beforehand // Variant and smart pointer test IUnknown. Ptr ip. Unk(CLSID_Simple. Object); // Create an object #1 _variant_t v. Value; v. Value. vt = VT_UNKNOWN; v. Value. punk. Val = ip. Unk; // What happens? ip. Magic = ip. Unk; ip. Magic->get_Reference. Count(&ref. Count); // Release these ip. Magic = 0; ip. Unk = 0; v. Value. punk. Val->Query. Interface(&ip. Magic 2); // What happens? ip. Magic 2 = 0; v. Value. vt = VT_EMPTY; // What happens now? What is missing from this code? Instructor Demo Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 14
HRESULTs u Always check HRESULTs returned by Arc. Objects u Use SUCCEEDED() or FAILED() macros u Non-zero severity means failed HRESULT hr; IWorkspace. Factory. Ptr ip. Workspace. Factory(CLSID_Access. Workspace. Factory); if (ip. Workspace. Factory == NULL) return E_FAIL; IWorkspace. Ptr ip. Workspace; if (FAILED(hr = ip. Workspace. Factory->Open. From. File(bstr. Database. Path, NULL, &ip. Workspace))) return hr; … Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 15
Formatting HRESULTs u Possible to get and display the error code message int main(int argc, char* argv[]) { IMap. Ptr ip. Map(CLSID_Map); IMx. Document ip. Mx. Doc; if (FAILED(hr = ip. Map->Query. Interface(&ip. Mx. Doc))) // Force a failed HRESULTMESSAGE(hr); } inline void HRESULTMESSAGE( HRESULT hr ) { LPVOID lp. Msg. Buf; : : Format. Message( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, // HRESULT MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lp. Msg. Buf, 0, NULL ); _TCHAR buf[256]; _stprintf( buf, "%s", (_TCHAR *) lp. Msg. Buf ); : : Local. Free( lp. Msg. Buf ); Message. Box(0, buf, _T("HRESULT ERROR MESSAGE"), MB_OK | MB_ICONINFORMATION ); } Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 16
Exception handling for DTC types u Native DTC classes throw _com_error exceptions u _com_error u Wraps IError. Info object u Returns: Description, Help. Context, Help. File, Source try { // Force smart pointer error. . . IMap. Ptr ip. Map; IActive. View. Ptr ip. AV; ip. Map->Query. Interface(&ip. AV); } catch (_com_error & err) { Error. Handler(err); } void Error. Handler(_com_error err) { _bstr_t bstr. Error; if (&err == NULL) return; bstr. Error = _T("Smart type error: "+ err. Description(). length() > 0 ? (LPCTSTR) err. Description() : err. Error. Message()); : : Message. Box(NULL, bstr. Error, _T("Generic Error"), MB_OK | MB_TASKMODAL); } Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 17
Developing console applications u Database related – Adding, deleting, and updating u Utility applications – Print jobs, describe feature classes int main(int argc, char* argv[]) { Co. Initialize(NULL); HRESULT hr; IFeature. Class. Ptr ip. Feature. Class; _bstr_t bstr. DBPath(L". . \Data\US. mdb"); _bstr_t bstr. FCName(L"States"); hr = Select. Feature. Class 1(bstr. DBPath, bstr. FCName, &ip. Feature. Class); if (FAILED(hr)) return -1; : : Message. Box(0, _T("Found feature class!"), _T("Console Applicaiton"), MB_OK); hr = Print. Feature. Class. Information(ip. Feature. Class); if (FAILED(hr)) return -1; : : Message. Box(0, _T("Printed feature class info!"), _T("Console Applicaiton"), MB_OK); Co. Uninitialize(); return 0; } Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 18
Writing Arc. Objects/Visual Studio exercises u Some VS projects are written from scratch u Format-related u All code inserts are prefixed with file name (e. g. , File. h) u ‘…’ means ‘scroll down until you find’ u Some u Bold steps have ‘step insert numbers’ means ‘write code’ Copyright © 2002 ESRI. All rights reserved. // MBFeature. h : Declaration of the CMBFeature … public: CMBFeature() : m_p. Inner. Unk(NULL) { } // ------ Step 2. 6 ----- DECLARE_GET_CONTROLLING_UNKNOWN() … BEGIN_COM_MAP(CMBFeature) COM_INTERFACE_ENTRY(ISupport. Error. Info) COM_INTERFACE_ENTRY(IFeature. Draw) END_COM_MAP() }; Advanced Arc. Objects Component Development II (C++) 19
More exercise hints… u Follow conventions u Project and class names u Project and file paths u Copy and paste Exercise. Functions. h file u Use exercise shortcuts u Be careful cutting and pasting solutions Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 20
Exercise 2 overview u Create a single Arc. Objects COM client u Import the esri. Core. olb correctly u Initialize the COM library u Accesses a geodatabase u Print featureclass name and field information u Challenge: Provide client-side error handling Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 21
Review u What is the first thing you need to do to work with Arc. Objects in VC++? u Why might you want to create an Arc. Objects consoletype application? u What are the dangers of using smart types? u True or False: VARIANT_TRUE = 1 and VARIANT_FALSE = 0? Copyright © 2002 ESRI. All rights reserved. Advanced Arc. Objects Component Development II (C++) 22
- Slides: 22