C++ sample¶
C++ drives the API as a COM client. Import the type library with #import to
generate strongly typed interface wrappers in the SIDRASolutions_SI_API
namespace, then activate the API with CoCreateInstance. This sample opens a
SIDRA project, processes every site, and prints its level of service and degree
of saturation.
Note
Complete the Getting started prerequisites first
(SIDRA Intersection installed, 64-bit, .NET 8). You also need a SIDRA
project (.sipx) file to open. Save one from SIDRA Intersection, or point
the sample at any existing project. Replace C:\Samples\Demo.sipx below
with its path. If anything fails, see Troubleshooting.
Important
Build for x64. The SIDRA API is x64-only; a 32-bit build fails to
activate it. The sample uses ATL helpers (CComPtr, CComBSTR), so build
with the Microsoft Visual C++ toolset (Visual Studio with the ATL
component installed).
1. Import the type library¶
The installer ships the type library SIDRASolutions.SI.API.tlb in the SIDRA
Intersection program folder. Import it with #import so the compiler generates
the interface declarations. The raw_interfaces_only attribute keeps the raw
get_/put_ accessors (rather than throwing wrapper methods), which is what
this sample uses.
#include <atlbase.h> // CComPtr, CComBSTR
#include <iostream>
// Adjust the path to match your install.
#import "C:\\Program Files\\SIDRA SOLUTIONS\\SIDRA INTERSECTION 11\\SIDRASolutions.SI.API.tlb" raw_interfaces_only
using namespace SIDRASolutions_SI_API;
2. Write the program¶
int main()
{
if (FAILED(CoInitialize(nullptr)))
{
std::wcerr << L"Failed to initialize COM.\n";
return 1;
}
{ // inner scope so every CComPtr releases before CoUninitialize()
CComPtr<ISIAPI> api;
if (FAILED(api.CoCreateInstance(__uuidof(SIAPI))))
{
std::wcerr << L"SIDRA Intersection COM API is not registered.\n";
CoUninitialize();
return 1;
}
VARIANT_BOOL opened = VARIANT_FALSE;
api->OpenProject(CComBSTR(L"C:\\Samples\\Demo.sipx"), &opened);
if (!opened)
{
CComBSTR error;
api->get_LastErrorMessage(&error);
std::wcerr << L"Could not open project: "
<< (error.m_str ? error.m_str : L"") << L"\n";
api->Close(&opened);
CoUninitialize();
return 1;
}
CComPtr<ISIAPIProject> project;
api->get_Project(&project);
CComBSTR projectName;
project->get_Name(&projectName);
std::wprintf(L"Project: %ls\n", projectName.m_str);
// Project -> SiteFolders -> Sites. In SIDRA a "site" is an intersection.
CComPtr<ISIAPISiteFolders> folders;
project->get_SiteFolders(&folders);
long folderCount = 0;
folders->get_Count(&folderCount);
for (long f = 0; f < folderCount; ++f)
{
CComPtr<ISIAPISiteFolder> folder;
folders->get_Item_2(f, &folder); // get_Item_2 retrieves by position
CComPtr<ISIAPISites> sites;
folder->get_Sites(&sites);
long siteCount = 0;
sites->get_Count(&siteCount);
for (long s = 0; s < siteCount; ++s)
{
CComPtr<ISIAPISite> site;
sites->get_Item_2(s, &site);
VARIANT_BOOL processed = VARIANT_FALSE;
site->Process(&processed); // run the analysis for this site
// Site-level vehicle results live under Outputset.OutputSiteVehicle.
CComPtr<ISIAPIOutputset> outputset;
site->get_Outputset(&outputset);
CComPtr<ISIAPIOutputSiteVehicle> result;
outputset->get_OutputSiteVehicle(&result);
CComBSTR siteName, los;
site->get_Name(&siteName);
result->get_Level_of_service(&los);
float degSatn = 0.0f;
result->get_Deg_satn(°Satn);
std::wprintf(L" %ls: LOS %ls, degree of saturation %.3f\n",
siteName.m_str, los.m_str, degSatn);
}
}
api->Close(&opened); // shuts down the SIDRA Intersection runtime
}
CoUninitialize();
return 0;
}
3. Build and run¶
Build the project for the x64 configuration in Visual Studio, then run the
resulting executable. The #import directive resolves at compile time and
generates the .tlh/.tli headers for the type library automatically.
Expected output (values depend on your project):
Project: Demo
North Rd / Main St: LOS B, degree of saturation 0.742
East Ave / Main St: LOS C, degree of saturation 0.871
Working with raw COM interfaces¶
With raw_interfaces_only, every member is a method that returns an HRESULT
and hands back its value through an out-parameter:
- Properties become
get_<Name>/put_<Name>calls.site.Namein the other samples issite->get_Name(&bstr)here. CComPtr<I...>owns the interface pointer and callsReleasefor you when it goes out of scope.CComBSTRowns string values, and booleans areVARIANT_BOOL(VARIANT_TRUE/VARIANT_FALSE).- Collections expose
get_Countand two indexers:get_Itemlooks up by name andget_Item_2retrieves by position (the same split the PowerShell sample notes). This sample iterates by position withget_Item_2.
See the API reference for the full surface. The per-member
pages show the C#, Python, and PowerShell forms; for C++, read a documented
property Foo as get_Foo / put_Foo and call methods directly, each
returning an HRESULT with results passed back through out-parameters.
Releasing the API¶
Call Close() when you are finished, then CoUninitialize(). Each CComPtr
releases its interface automatically when it leaves scope, so keep the API
objects in a narrower scope than the CoUninitialize() call, as the sample
does above. Releasing the COM objects after the apartment has already been torn
down is undefined behaviour.