Getting Started with C# (.NET)¶
The Spinnaker .NET (Managed) API provides a managed wrapper for Windows desktop applications, GUI integration, and .NET environments.
Prerequisites¶
- Spinnaker SDK installed (download)
- Visual Studio 2015 or later on Windows
- .NET Framework
- A supported Teledyne camera connected via USB3 or GigE
Basic Acquisition Example¶
The canonical example is located at src/Acquisition_CSharp/Acquisition_CSharp.cs
in the SDK. Below is the essential workflow:
using SpinnakerNET;
using SpinnakerNET.GenApi;
class Program
{
static void Main(string[] args)
{
// Get the system singleton
ManagedSystem system = new ManagedSystem();
// Retrieve camera list
IList<IManagedCamera> camList = system.GetCameras();
// Get the first camera
IManagedCamera cam = camList[0];
// Initialize
cam.Init();
// Configure acquisition mode
INodeMap nodeMap = cam.GetNodeMap();
IEnum acquisitionMode = nodeMap.GetNode<IEnum>("AcquisitionMode");
acquisitionMode.Value = "Continuous";
// Begin acquisition
cam.BeginAcquisition();
// Retrieve images
for (int i = 0; i < 10; i++)
{
using (IManagedImage rawImage = cam.GetNextImage(1000))
{
if (!rawImage.IsIncomplete)
{
Console.WriteLine(
"Image {0}: {1} x {2}",
i, rawImage.Width, rawImage.Height);
}
}
}
// Clean up
cam.EndAcquisition();
cam.DeInit();
cam.Dispose();
camList.Clear();
system.Dispose();
}
}
Key Concepts¶
Managed Image Lifecycle¶
Use using blocks or explicitly call Dispose() to release images and prevent
buffer exhaustion.
Node Access¶
Access GenICam nodes through the managed wrapper:
INodeMap nodeMap = cam.GetNodeMap();
IFloat exposureTime = nodeMap.GetNode<IFloat>("ExposureTime");
exposureTime.Value = 10000.0;
Feature Snippets¶
Hardware Triggering¶
Configure the camera for asynchronous hardware triggering on GPIO Line 0 (rising edge):
IEnum triggerMode = nodeMap.GetNode<IEnum>("TriggerMode");
triggerMode.Value = "On";
IEnum triggerSource = nodeMap.GetNode<IEnum>("TriggerSource");
triggerSource.Value = "Line0";
IEnum triggerSelector = nodeMap.GetNode<IEnum>("TriggerSelector");
triggerSelector.Value = "FrameStart";
IEnum triggerActivation = nodeMap.GetNode<IEnum>("TriggerActivation");
triggerActivation.Value = "RisingEdge";
Setting Exposure Time¶
Set the exposure/shutter time to 20 milliseconds (20000 microseconds):
Setting Gain¶
Adjust analog gain to 10.5 dB:
Event Handling¶
Spinnaker provides two event classes: interface events (device arrival/removal) and device events (camera-specific events such as end of exposure).
// Interface event — device arrival and removal
class InterfaceEventListener : ManagedInterfaceEvent
{
protected override void OnDeviceArrival()
{
Console.Out.WriteLine("A new device has arrived!");
}
protected override void OnDeviceRemoval(UInt64 serialNumber)
{
Console.Out.WriteLine(
"A device with serial number {0} has been removed!",
serialNumber);
}
}
// Device event — configure ExposureEnd notification
cam.EventSelector.Value = EventSelectorEnums.EventExposureEnd.ToString();
cam.EventNotification.Value = EventNotificationEnums.On.ToString();
// After registering on the camera, OnDeviceEvent is called when ExposureEnd fires
class ManagedDeviceEventHandler : ManagedDeviceEvent
{
protected override void OnDeviceEvent(string eventName)
{
Console.Out.WriteLine(
"Got Device Event with Name=" + eventName + " and ID= {0}",
GetDeviceEventId());
}
}
Grabbing Images¶
Use GetNextImage() to retrieve images. Always release the image pointer when done — the managed image pointer is automatically released when set to null or when it goes out of scope.
// Begin capturing images
cam.BeginAcquisition();
// Retrieve an image
ManagedImage rawImage = cam.GetNextImage();
// Release image
rawImage.Release();
Check whether the grabbed image contains errors:
Error Handling¶
Spinnaker C# uses SpinnakerException for exception handling:
Chunk Data¶
Chunk data allows the camera to append metadata (frame counter, width, height, exposure time, etc.) to each image.
// Enable chunk data for ExposureTime
cam.ChunkSelector.Value = ChunkSelectorEnums.ExposureTime.ToString();
cam.ChunkEnable.Value = true;
cam.ChunkModeActive.Value = true;
// Retrieve chunk data from an acquired image
String currentExposure = rawImage.ChunkData.ExposureTime.ToString();
Logging¶
Spinnaker supports five logging levels: Error, Warn, Notice, Info, and Debug. Levels are inclusive — monitoring Debug also captures all levels above it. By default, SpinView saves logs to C:\ProgramData\Spinnaker\Logs.
// Register logging callback class
LogCallbackHandler callBackClass = new LogCallbackHandler();
system.RegisterLoggingEvent(callBackClass);
// Set callback priority level
system.SetLoggingEventPriorityLevel(LoggingLevel);
class LogCallbackHandler : ManagedLoggingEventHandler
{
public override void OnLogEvent(ManagedLoggingEvent loggingEvent)
{
// Process log event
}
}
Design Conventions¶
Disposal Pattern¶
ManagedSystem, IManagedCamera, and IManagedImage wrap native C++ handles
and implement IDisposable. Always use using blocks or explicitly call
.Dispose() — do not rely on the GC to release native resources:
using var system = new ManagedSystem();
using var cameras = system.GetCameras();
IManagedCamera cam = cameras[0];
cam.Init();
try
{
cam.BeginAcquisition();
// ... acquire ...
cam.EndAcquisition();
}
finally
{
cam.Dispose();
}
Event Handling¶
The .NET API exposes camera and system events as strongly-typed registrations. Implement a handler class and register it before acquisition:
public class MyImageHandler : ManagedImageEventHandler
{
override public void OnImageEvent(IManagedImage image)
{
Console.WriteLine($"Frame: {image.Width}x{image.Height}");
}
}
var handler = new MyImageHandler();
cam.RegisterEvent(handler);
cam.BeginAcquisition();
// ... handler fires on each frame ...
cam.EndAcquisition();
cam.UnregisterEvent(handler);
Error Handling¶
The .NET API throws SpinnakerException on failure, compatible with standard
.NET Exception patterns:
try
{
cam.BeginAcquisition();
}
catch (SpinnakerException ex)
{
Console.WriteLine($"Acquisition failed: {ex.Message}");
}
Quick Reference¶
System & Discovery¶
| Class / Method | Description |
|---|---|
ManagedSystem |
System singleton — entry point for the SDK |
ManagedSystem.GetCameras() |
Enumerate connected cameras |
ManagedSystem.GetLibraryVersion() |
Query SDK version at runtime |
Camera Lifecycle¶
| Class / Method | Description |
|---|---|
ManagedCameraList |
Enumerable list of detected cameras |
IManagedCamera |
Camera interface for configuration and acquisition |
IManagedCamera.Init() |
Initialize the camera and populate node map |
IManagedCamera.DeInit() |
De-initialize the camera |
IManagedCamera.BeginAcquisition() |
Start image acquisition |
IManagedCamera.EndAcquisition() |
Stop image acquisition |
Image Handling¶
| Class / Method | Description |
|---|---|
IManagedImage |
Captured image with pixel data access |
IManagedImage.IsIncomplete |
Check for dropped or incomplete frame |
IManagedImage.Width / Height |
Image dimensions in pixels |
IManagedImage.PixelFormat |
Current pixel format |
IManagedImage.Release() |
Return image to acquisition buffer pool |
ManagedImageProcessor |
Image format conversion utility |
ManagedImageProcessor.Convert() |
Convert to a different pixel format |
Node Map & Configuration¶
| Class / Method | Description |
|---|---|
IManagedCamera.GetNodeMap() |
Access GenICam node map (requires Init()) |
IManagedCamera.GetTLDeviceNodeMap() |
Transport layer device node map (pre-Init()) |
IManagedCamera.GetTLStreamNodeMap() |
Transport layer stream node map |
IManagedNodeMap |
GenICam node map access for camera configuration |
IInteger / IFloat / IBoolean / IEnumeration |
Typed GenICam node interfaces |
Events & Callbacks¶
| Class | Description |
|---|---|
ManagedImageEventHandler |
Base class for image arrival callbacks |
ManagedDeviceEventHandler |
Base class for device-level events |
ManagedLoggingEventHandler |
Base class for SDK log message callbacks |
IManagedCamera.RegisterEvent() |
Attach an event handler to a camera |
IManagedCamera.UnregisterEvent() |
Detach an event handler |
Exception Reference¶
The .NET API signals all errors by throwing SpinnakerException. It inherits
from System.Exception and additionally exposes the SDK error code:
| Member | Description |
|---|---|
Message |
Human-readable error description |
ErrorCode |
Numeric SDK error code (spinError) |
FileName |
Source file where the error originated |
FunctionName |
Function name where the error originated |
LineNumber |
Line number where the error originated |
FullErrorMessage |
Concatenated full error details |
Common error codes are listed in the C API Error Code Reference.
Known Issues & Limitations¶
Windows Only
The Spinnaker .NET API is supported on Windows only. For cross-platform deployments, use the C API or Python API.
Garbage Collection & Native Resources
The GC does not guarantee timely cleanup of native camera handles.
Always use using blocks or explicit .Dispose() calls — do not
rely on finalizers for camera or image objects.
Further Reading¶
- C# API Reference — Full class and method documentation
- Programmer's Guide — GenICam nodes, QuickSpin, sequencer, and more
- Streaming Drivers — GigE driver configuration
- SDK Example: Acquisition_CSharp — Full acquisition example
- SDK Example: Trigger_CSharp — Hardware and software triggering
- SDK Example: Exposure_CSharp — Exposure control