![]() |
IDS peak genericC++
v1.7.2
|
The IDS peak genericAPI is a library that unites GenTL and GenApi. In some places, it also introduces some extra functionality. The purpose of this extra functionality is to increase the usability and comfort of the standard GenAPI.
The classes in the core namespace are mostly a tight wrapper around the GenAPI and GenTL. It provides some convenience by automatic resource cleanup (RAII), but mostly it reflects the hierarchical structure of the GenTL:
Each module can list the Descriptors of its child modules, which can open the corresponding child module.
Each module needs its parent module to function properly. Therefore, you need to keep the parent modules around until you are done with the child module. When using the DeviceManager, it keeps the ProducerLibrary, System, and Interface modules open until program termination (or until calling DeviceManager::Reset()).
The main peak namespace contains global library functions as well as convenience functionality, which don't exist in GenAPI/GenTL. The convenience functionality simplifies the standard usage of the API, without sacrificing access to the more complex API in the core namespace.
Before doing anything else, call Library::Initialize(). This will initialize any needed resources. Calling any other function before calling Library::Initialize() will result in a NotInitializedException.
After you are done using the library, call Library::Close() before unloading the library. This will clean up any internal resources and stop any running threads.
A common way to start programming with the IDS peak genericAPI is to enumerate the GenTL producer libraries found in the current environment. This is achieved by calling EnvironmentInspector::CollectCTIPaths(). Once you have chosen a producer library, you pass its path to the static method ProducerLibrary::Open(). From there, you can follow the hierarchical structure of the modules: ProducerLibrary -> System -> Interface -> Device -> DataStream. Each Module can list and open its child-modules.
If you don't need tight control over when modules are opened and closed, you can also use the DeviceManager. It provides much more convenience by enabling you to enumerate all modules of the available producer libraries with a single function call (DeviceManager::Update()):
To enumerate the Devices, the underlying modules (i.e. ProducerLibraries, Systems, and Interfaces) need to be opened. Since the DeviceManager is a singleton, these modules stay open until program termination or until DeviceManager::Reset() is called.
*.ctis using GenTL v1.1 or higher are supported. When accessing features the *.cti doesn't support, there will be a "not implemented" error. E.g. chunks exist since GenTL v1.3, so trying to access chunks with a GenTL v1.2 *.cti will result in a exception. GenTL v1.0 *.ctis are not supported.
The IDS peak genericAPI exists as a plain C-API, so it can be integrated in any programming environment. As a wrapper around the the C-API, there is also a more convenient C++ API. These C++ wrapper classes are implemented as header-only, so there are no compiler incompatibilities.
This API uses the concept of descriptors acting as delegates for all openable modules. A descriptor holds information about its module and can open its module.
This API uses smart pointers to automatically release unused resources. This makes the interaction with the API very intuitive. As an example the descriptors' open functions return a smart pointer holding the opened module. If the user releases the last smart pointer referencing the opened module, the module automatically gets closed and destroyed. The same applies to the event controller returned by EventSupportingModule::EnableEvents(). After releasing the last smart pointer referencing the event controller, the corresponding event type is disabled automatically and the event controller itself is destroyed.
By default, this library is linked into the user program, therefore is loaded statically at program start. Instead, it can also be loaded dynamically, when the first library function is called. To use this feature, enable the CMake option PEAK_DYNAMIC_LOADING or set the #define PEAK_DYNAMIC_LOADING before including any of the libraries files.
For Windows, there is also a .NET version of the library.
To use it in a C# project, add a reference to the ids_peak_dotnet.dll to the project.
Before starting your application, make sure that the DLL-Loader can find all required libraries. This means that ids_peak_dotnet.dll, ids_peak_dotnet_interface.dll, ids_peak.dll and all GenICam libraries required by ids_peak.dll are located next to your application binary or that the directory where they are located is added to the DLL-Loader's search directories. To add their directory to the DLL-Loader's search directories, you could simply append their directory to the environment variable 'Path':
PowerShell:
CMD:
The .NET API works much like the C++ API. The same principles, class and method names apply. For example, listing all available devices:
There are a few differences between the C++ API and the .NET API. The most important ones are listed here:
| C++ | C# / .NET |
|---|---|
Deterministic Memory Management To close a module (e.g. the Device), you have to release its shared_ptr (out-of-scope, call reset(), set to nullptr), then the module closes immediately. { auto device = deviceDescriptors[0].OpenDevice(DeviceAccessType.Control); // ... } // Device closes here | Garbage Collection When an object is relased in C#, it won't be closed and deleted immediately. Instead, it will be deleted at some point in the future, when the garbage collection deems it necessary. Often, that's no problem. But if it is, there are 2 options:
|
| Callbacks device_manager.RegisterDeviceFoundCallback( [](const std::shared_ptr<peak::core::DeviceDescriptor>& newDev) { std::cout << "Device found: " << newDev->DisplayName() << '\n'; }); | Events + Delegates deviceManager.DeviceFoundEvent += (object o, DeviceDescriptor newDev) => Console.WriteLine("Device found: {0}", newDev.DisplayName()); |
| Method Default Parameters DataStream::StartAcquisition( AcquisitionStartMode mode=AcquisitionStartMode::Default, uint64_t numToAcquire=INFINITE_NUMBER); | Method Overloads DataStream.StartAcquisition(peak.core.AcquisitionStartMode mode, ulong numToAcquire) DataStream.StartAcquisition(peak.core.AcquisitionStartMode mode) // with numToAcquire=INFINITE_NUMBER DataStream.StartAcquisition() // with mode=Default and numToAcquire=INFINITE_NUMBER |
| Function templates nodeMapRemoteDevice->FindNode<peak::core::nodes::StringNode>("DeviceModelName")->Value() | Generic method wrappers C# also supports function templates (i.e. generic methods), which can be used as follows: nodeMapRemoteDevice.FindNode<peak.core.nodes.StringNode>("DeviceModelName").Value()); However, some IDE's and/or .NET implementations might not support such generic methods (e.g. NI Labview). Therefore all template specifications have been made available separately: nodeMapRemoteDevice.FindNodeString("DeviceModelName").Value()); |
To use IDS peak genericAPI in Python, there is a separate Python wheel for each supported Python version and CPU architecture. A Python wheel is a package file (with .whl file ending) which can be installed via 'pip', Python's package manager. Just call 'pip install <Path-To-Python-Wheel>' to install your chosen Python wheel.
To finally use IDS peak genericAPI in your Python script, just add 'import ids_peak.ids_peak' or 'import ids_peak.ids_peak as some_alias' at the top of your Python script. The latter should be preferred.
The Python API works much like the C++ API. Nearly the same principles, class and method names apply. For example, listing all available devices:
There are only a few differences between the C++ API and the Python API. The most important ones are listed here:
| C++ | Python |
|---|---|
Deterministic Memory Management To close a module (e.g. the Device), you have to release its shared_ptr (out-of-scope, call reset(), set to nullptr), then the module closes immediately. { auto device = deviceDescriptors[0].OpenDevice(DeviceAccessType.Control); // ... } // Device gets closed here | Garbage Collection When an object is relased in Python, it won't be closed and deleted immediately. Instead, it will be deleted at some point in the future, when the garbage collection deems it necessary. Often, that's no problem. But if it is, you could do the following: device = deviceDescriptors[0].OpenDevice(some_alias.DeviceAccessType_Control) del device # Device gets closed here |
| Enums const auto deviceAccessType = DeviceAccessType::Control; std::cout << ToString(deviceAccessType) << '\n'; | Enums device_access_type = some_alias.DeviceAccessType_Control print(some_alias.DeviceAccessTypeEnumEntryToString(device_access_type)) |
| Callbacks const auto deviceFoundCallbackHandle = deviceManager.RegisterDeviceFoundCallback( [](const std::shared_ptr<peak::core::DeviceDescriptor>& newDev) { std::cout << "Device found: " << newDev->DisplayName() << '\n'; }); deviceManager.Update() deviceManager.UnregisterDeviceFoundCallback(deviceFoundCallbackHandle); | Callbacks device_found_callback = device_manager.DeviceFoundCallback( lambda new_dev: print("Device found: {}", new_dev.DisplayName())) device_found_callback_handle = device_manager.RegisterDeviceFoundCallback(device_found_callback) device_manager.Update() device_manager.UnregisterDeviceFoundCallback(device_found_callback_handle) |