Using the Scripting Interface with C++: Examples
Examples are provided below of using the Scripting Interface with C++ in eCADSTAR Library Editor,eCADSTAR Schematic Editor and eCADSTAR PCB Editor. The procedures are also provided for using Iterator-based and Range-based loops. To download scripting examples, click: Scripting Examples. For a specified design, these provide a list of components and their associated parts. Browse to the C++ folder in the downloaded data.
To Display All Part Properties in a Library
#include <iostream>
#import "C:\Program Files\eCADSTAR\eCADSTAR 2021.0\bin\eCS_le.exe"
class COMInitializer
{
public:
COMInitializer()
{
CoInitializeEx(nullptr, COINITBASE_MULTITHREADED);
}
~COMInitializer()
{
CoUninitialize();
}
};
int main(int argc, char* argv[])
{
using namespace eCSLECOM;
std::wcout.imbue(std::locale(""));
if(argc < 2)
{
return 1;
}
COMInitializer co;
// Launch eCADSTAR Library Editor.
ILEApplicationPtr app;
app.CreateInstance(__uuidof(LEApplication));
app->OpenDesign(argv[1]);
ILEPartsPtr parts= app->Library->Parts;
for(long ic = 1; ic <= parts->Count; ic++)
{
ILEPartPtr part= part->Item[ic];
IPropertiesPtr properties = part->Properties;
for(long ip = 1; ip <= properties->Count; ip++)
{
IPropertyPtr property = properties->Item[ip];;
std::wcout << property->Name << " : " << property->Value << std::endl;
}
}
app->Quit();
return 0;
}
To Display All Sheet Properties in a Schematic Design
#include <iostream>
#import "C:\Program Files\eCADSTAR\eCADSTAR 2019.0\bin\eCS_scm.exe"
class COMInitializer
{
public:
COMInitializer()
{
CoInitializeEx(nullptr, COINITBASE_MULTITHREADED);
}
~COMInitializer()
{
CoUninitialize();
}
};
int main(int argc, char* argv[])
{
using namespace eCSSCHCOM;
std::wcout.imbue(std::locale(""));
if(argc < 2)
{
return 1;
}
COMInitializer co;
// Launch eCADSTAR Schematic Editor.
ISchApplicationPtr app;
app.CreateInstance(__uuidof(SchApplication));
app->OpenDesign(argv[1]);
ISchSheetsPtr sheets = app->Design->Sheets;
for(long is = 1, ns = sheets->Count; is <= ns; ++is)
{
ISchSheetPtr sheet = sheets->Item[is];
sheet->Open();
std::wcout << sheet->Number << std::endl;
IPropertiesPtr properties = sheet->Properties;
for(long ip = 1, np = properties->Count; ip <= np; ++ip)
{
IPropertyPtr property = properties->Item[ip];
std::wcout << property->Name << " : " << property->Value << std::endl;
}
sheet->Close();
}
app->Quit();
return 0;
}
To Display All Component Properties in a PCB Design
#include <iostream>
#import "C:\Program Files\eCADSTAR\eCADSTAR 2019.0\bin\eCS_pcb.exe"
class COMInitializer
{
public:
COMInitializer()
{
CoInitializeEx(nullptr, COINITBASE_MULTITHREADED);
}
~COMInitializer()
{
CoUninitialize();
}
};
int main(int argc, char* argv[])
{
using namespace eCSPCBCOM;
std::wcout.imbue(std::locale(""));
if(argc < 2)
{
return 1;
}
COMInitializer co;
// Launch eCADSTAR PCB Editor.
IPCBApplicationPtr app;
app.CreateInstance(__uuidof(PCBApplication));
app->OpenDesign(argv[1]);
IPCBComponentsPtr components = app->CurrentDesign->Components;
for(long ic = 1; ic <= components->Count; ic++)
{
IPCBComponentPtr component = components->Item[ic];
IPropertiesPtr properties = component->Properties;
for(long ip = 1; ip <= properties->Count; ip++)
{
IPropertyPtr property = properties->Item[ip];;
std::wcout << property->Name << " : " << property->Value << std::endl;
}
}
app->Quit();
return 0;
}
Using Iterator-based Loops
By default, COM collections are not available in C++. However, you can define an iterator that wraps IEnumVARIANT, and provides begin and end functions. This enables COM collections to handle the range concept. This is shown in the following example.
template<class IItemPtr>
class IEnumVARIANT_iterator
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = IItemPtr;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
IEnumVARIANT_iterator() = default;
IEnumVARIANT_iterator(IEnumVARIANTPtr p):enumVariant_(p)
{
operator++();
}
IEnumVARIANT_iterator& operator++()
{
_variant_t v;
ULONG c = 0;
if(enumVariant_ && enumVariant_->Next(1, &v, &c) == S_OK)
{
v.pdispVal->QueryInterface<typename IItemPtr::Interface>(&item_);
}
else
{
enumVariant_ = nullptr;
item_ = nullptr;
}
return *this;
}
operator bool(){ return static_cast<bool>(item_); }
bool operator==(const IEnumVARIANT_iterator& rhs) const noexcept { return item_ == rhs.item_; }
bool operator!=(const IEnumVARIANT_iterator& rhs) const noexcept { return item_ != rhs.item_; }
reference operator*() noexcept { return item_; }
value_type operator*() const noexcept { return item_; }
pointer operator->() noexcept { return &item_; }
const pointer operator->() const noexcept { return &item_; }
private:
IEnumVARIANTPtr enumVariant_;
IItemPtr item_;
};
template<typename _IIID>
auto begin(const _com_ptr_t<_IIID>& p)
{
return IEnumVARIANT_iterator<decltype(p->Item[0])>{ p->_NewEnum };
}
template<typename _IIID>
auto end(const _com_ptr_t<_IIID>& p)
{
return IEnumVARIANT_iterator<decltype(p->Item[0])>{ nullptr };
}
Using Range-based loops over COM Collections
The following iterator definition allows you to use range-based loops over COM collections.
int main(int argc, char* argv[])
{
using namespace eCSSCHCOM;
std::wcout.imbue(std::locale(""));
if(argc < 2)
{
return 1;
}
COMInitializer co;
ISchApplicationPtr app;
app.CreateInstance(__uuidof(SchApplication));
app->OpenDesign(argv[1]);
for(ISchSheetPtr sheet : app->Design->Sheets)
{
sheet->Open();
std::wcout << sheet->Number << std::endl;
for(IPropertyPtr property : sheet->Properties)
{
std::wcout << property->Name << " : " << property->Value << std::endl;
}
sheet->Close();
}
app->Quit();
return 0;
}