IDS peak genericC++ v1.15.0
Loading...
Searching...
No Matches
C# / .NET

Prerequisites

To use IDS peak genericAPI in dotnet, the IDSImaging.Peak.API package can be installed directly from NuGet via dotnet:

dotnet add package IDSImaging.Peak.API

The package targets .NET Standard 2.0, making it compatible with:

  • .NET Framework 4.6.1 and later
  • .NET 5 and later
Note
A separate installation of the runtime setup is required. This provides the necessary Transport Layer (TL) components for communicating with the camera.

Build Instructions

The IDSImaging.Peak.API relies on native (unmanaged) DLLs that are distributed inside the referenced NuGet packages.

Because native binaries are involved, you must specify the target architecture via -p:Platform=<arch> when building. This ensures that your application is built for an architecture that can correctly load the required native libraries.

If no RuntimeIdentifier (-r) is specified, all available native runtimes from the packages will be copied to your build output. This would normally maximize compatibility but increase the application size. However, when the Platform parameter is specified, other architectures are not supported (except for x86 on x64).

You may optionally specify -r <rid> to reduce the size of the build output by including only the native libraries for a single runtime.

.NET (modern, SDK-style)

Required (correct architecture selection):

dotnet build -p:Platform=x64 exampleProject.csproj
dotnet run -p:Platform=x64 --project exampleProject.csproj

Optional (smaller output):

dotnet build -r win-x64 -p:Platform=x64 exampleProject.csproj
dotnet run -r win-x64 -p:Platform=x64 --project exampleProject.csproj

You can substitute another architecture/runtime pair if needed, e.g.:

-p:Platform=x86 (optionally with -r win-x86)
-p:Platform=x64 with -r linux-x64

.NET Framework (classic)

Use Visual Studio or build from the command line:

Restore packages first

msbuild exampleProjectFramework.csproj /t:Restore

Build for a specific platform (required for native DLLs)

msbuild exampleProjectFramework.csproj /p:Platform=x64

Usage

The .NET API works much like the C++ API. The same principles, class and method names apply. For example, listing all available devices:

using IDSImaging.Peak.API;
try
{
Library.Initialize();
var deviceManager = DeviceManager.Instance();
deviceManager.Update();
var deviceDescriptors = deviceManager.Devices();
foreach (var deviceDescriptor in deviceDescriptors)
{
Console.WriteLine(deviceDescriptor.DisplayName());
}
}
catch (System.ApplicationException e)
{
Console.WriteLine("Exception: " + e.Message);
}
Warning
The DeviceManager is incompatible with using statements or declarations, since it is implemented as a singleton. Being part of a using statement or declaration would result in Dispose() being called on the DeviceManager at the end of the scope. Further use of the reference returned by DeviceManager.Instance would then result in a crash, since that instance has been disposed already.

Converting a Buffer to an Image

It is possible to convert the content of a Buffer into an image by directly employing Buffer::BasePtr alongside a custom conversion routine to ensure compatibility with any image processing library. However, the recommended method is to use the BufferToImage function. This function is included in the supplementary assembly IDSImaging.Peak.API.IPLExtension.dll. BufferToImage is specifically engineered to simplify the conversion process of raw memory data stored within a Buffer into an peak::ipl::Image that can be used for further processing.

In order to make use of this functionality, an assembly reference must be added to the project and the IDSImaging.Peak.API.IPLExtension.dll needs to be available. See the Prerequisites section above for further instructions or use one of the provided samples that are shipped with the SDK as a starting template.

An example usage could look like as follows:

// Get buffer from device's data stream
var buffer = dataStream.WaitForFinishedBuffer(1000);
// Create peak::ipl::Image (shallow copy)
using var image = IDSImaging.Peak.API.IPLExtension.BufferToImage(buffer);
Warning
The resulting image still uses the underlying memory of buffer. For this reason, you must ensure that you do not re-queue the buffer until you have finished processing image.

Comparison to the C++ API

There are a few differences between the C++ API and the .NET API. The most important ones are listed here:

Resource Management

The C++ API utilizes smart pointers for deterministic memory management, where the last smart pointer that holds a reference to the object destroys it when the smart pointer goes out of scope.

To close a module (e.g. the Device), you have to release all its shared_ptr instances (out-of-scope, call reset(), set to nullptr), then the module closes immediately.

  • C++
    {
    auto device = deviceDescriptors[0].OpenDevice(DeviceAccessType.Control);
    // ...
    } // Device closes here

By default, C# uses garbage collection to manage memory and resources. As a result, an object without any active references is not immediately closed or deleted. Instead, it will be removed by the garbage collector at an unspecified point in the future.

However, many peak objects hold resources that are not managed by the garbage collector, known as unmanaged resources. When working with unmanaged resources, it is essential to release them as soon as they are no longer needed. This can be achieved using one of the following methods:

Call Dispose() explicitly:

  • C#
    var device = deviceDescriptors[0].OpenDevice(DeviceAccessType.Control);
    // do something with device...
    device.Dispose(); // Device is closed here

Or let a using statement handle calling Dispose() at the end of the scope:

  • C#
    using (var device = deviceDescriptors[0].OpenDevice(DeviceAccessType.Control))
    {
    // do something with device...
    } // Device is closed here

It is important to release unmanaged resources in the reverse order in which they were acquired:

  • C#
    var device = deviceDescriptors[0].OpenDevice(DeviceAccessType.Control);
    using (var nodemap = device.RemoteDevice().NodeMaps()[0])
    {
    var frameRateNode = nodemap.FindNode<FloatNode>("AcquisitionFrameRate");
    frameRateNode.SetValue(5);
    } // Nodemap is closed here
    var dataStream = device.DataStreams()[0].OpenDataStream();
    var grabbing = dataStream.IsGrabbing();
    dataStream.Dispose(); // DataStream is closed here
    device.Dispose(); // Device is closed here

Change Notification

To be notified when certain events happen, the C++ API employs callbacks that you have to register and unregister. C# has the concept of events built-in and similarly to C++ you have to register a delegate as an event handler:

  • C++ Callbacks
    device_manager.RegisterDeviceFoundCallback(
    [](const std::shared_ptr<peak::core::DeviceDescriptor>& newDev)
    { std::cout << "Device found: " << newDev->DisplayName() << '\n'; });
  • C# Events + Delegates
    deviceManager.DeviceFoundEvent += (object o, DeviceDescriptor newDev)
    => Console.WriteLine("Device found: {0}", newDev.DisplayName());

Overloads vs. Default Parameters

While C# supports optional parameters as well, the current C# API provides an overload for each default parameter instead:

  • C++ Method Default Parameters
    DataStream::StartAcquisition(
    AcquisitionStartMode mode=AcquisitionStartMode::Default,
    uint64_t numToAcquire=INFINITE_NUMBER);
  • C# Method Overloads
    DataStream.StartAcquisition(IDSImaging.Peak.API.Core.AcquisitionStartMode mode, ulong numToAcquire)
    DataStream.StartAcquisition(IDSImaging.Peak.API.Core.AcquisitionStartMode mode) // with numToAcquire=INFINITE_NUMBER
    DataStream.StartAcquisition() // with mode=Default and numToAcquire=INFINITE_NUMBER

Generic Methods

C# also supports function templates (i.e. generic methods), which can be used as follows:

  • C++ Function Templates
    nodeMapRemoteDevice->FindNode<peak::core::nodes::StringNode>("DeviceModelName")->Value()
    Represents a GenAPI string node.
    Definition peak_string_node.hpp:36
  • C# Generic Methods
    nodeMapRemoteDevice.FindNode<IDSImaging.Peak.API.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:

  • C#
    nodeMapRemoteDevice.FindNodeString("DeviceModelName").Value());