Skip to content

Getting Started with C

The Spinnaker C API provides a handle-based interface for embedded systems and environments where C++ exceptions are not suitable.

Prerequisites

  • Spinnaker SDK installed (download)
  • C compiler (Visual Studio 2015+ on Windows, GCC on Linux, Clang on macOS)
  • A supported Teledyne camera connected via USB3 or GigE

Basic Acquisition Example

The canonical example is located at src/Acquisition_C/Acquisition_C.c in the SDK. Below is the essential workflow:

#include "SpinnakerC.h"

int main()
{
    spinError err = SPINNAKER_ERR_SUCCESS;

    // Get the system
    spinSystem hSystem = NULL;
    err = spinSystemGetInstance(&hSystem);

    // Retrieve camera list
    spinCameraList hCameraList = NULL;
    err = spinCameraListCreateEmpty(&hCameraList);
    err = spinSystemGetCameras(hSystem, hCameraList);

    // Get the first camera
    spinCamera hCam = NULL;
    err = spinCameraListGet(hCameraList, 0, &hCam);

    // Initialize
    err = spinCameraInit(hCam);

    // Begin acquisition
    err = spinCameraBeginAcquisition(hCam);

    // Retrieve images
    for (int i = 0; i < 10; i++)
    {
        spinImage hImage = NULL;
        err = spinCameraGetNextImageEx(hCam, 1000, &hImage);

        bool8_t isIncomplete = False;
        spinImageIsIncomplete(hImage, &isIncomplete);

        if (!isIncomplete)
        {
            size_t width = 0, height = 0;
            spinImageGetWidth(hImage, &width);
            spinImageGetHeight(hImage, &height);
            printf("Image %d: %zu x %zu\n", i, width, height);
        }

        // Release image
        spinImageRelease(hImage);
    }

    // Clean up
    err = spinCameraEndAcquisition(hCam);
    err = spinCameraDeInit(hCam);
    err = spinCameraRelease(hCam);
    err = spinCameraListClear(hCameraList);
    err = spinCameraListDestroy(hCameraList);
    err = spinSystemReleaseInstance(hSystem);

    return 0;
}

Key Concepts

Error Handling

Every C API function returns a spinError value. Always check return codes:

spinError err = spinCameraInit(hCam);
if (err != SPINNAKER_ERR_SUCCESS)
{
    printf("Error initializing camera: %d\n", err);
    return -1;
}

Node Access

Use node handle functions to access GenICam features:

spinNodeMapHandle hNodeMap = NULL;
spinCameraGetNodeMap(hCam, &hNodeMap);

spinNodeHandle hAcquisitionMode = NULL;
spinNodeMapGetNode(hNodeMap, "AcquisitionMode", &hAcquisitionMode);

Feature Snippets

Hardware Triggering

// Enable trigger mode on Line 0 (rising edge)
spinNodeHandle hTriggerMode = NULL;
spinNodeHandle hTriggerModeOn = NULL;
int64_t triggerModeOn = 0;

spinNodeMapGetNode(hNodeMap, "TriggerMode", &hTriggerMode);
spinEnumerationGetEntryByName(hTriggerMode, "On", &hTriggerModeOn);
spinEnumerationEntryGetValue(hTriggerModeOn, &triggerModeOn);
spinEnumerationSetIntValue(hTriggerMode, triggerModeOn);

spinNodeHandle hTriggerSource = NULL;
spinNodeHandle hTriggerSourceLine0 = NULL;
int64_t triggerSourceLine0 = 0;

spinNodeMapGetNode(hNodeMap, "TriggerSource", &hTriggerSource);
spinEnumerationGetEntryByName(hTriggerSource, "Line0", &hTriggerSourceLine0);
spinEnumerationEntryGetValue(hTriggerSourceLine0, &triggerSourceLine0);
spinEnumerationSetIntValue(hTriggerSource, triggerSourceLine0);

See also: src/Trigger_C/Trigger_C.c

Setting Exposure Time

// Turn off auto exposure
spinNodeHandle hExposureAuto = NULL;
spinNodeHandle hExposureAutoOff = NULL;
int64_t exposureAutoOff = 0;

spinNodeMapGetNode(hNodeMap, "ExposureAuto", &hExposureAuto);
spinEnumerationGetEntryByName(hExposureAuto, "Off", &hExposureAutoOff);
spinEnumerationEntryGetValue(hExposureAutoOff, &exposureAutoOff);
spinEnumerationSetIntValue(hExposureAuto, exposureAutoOff);

// Set ExposureTime to 20000 microseconds (20 ms)
spinNodeHandle hExposureTime = NULL;
spinNodeMapGetNode(hNodeMap, "ExposureTime", &hExposureTime);
spinFloatSetValue(hExposureTime, 20000.0);

Grabbing Images

spinImage hResultImage = NULL;

// Begin acquisition
spinCameraBeginAcquisition(hCam);

// Retrieve image
spinCameraGetNextImageEx(hCam, 1000, &hResultImage);

// Check for errors
spinImageStatus imageStatus = IMAGE_NO_ERROR;
spinImageGetStatus(hResultImage, &imageStatus);

bool8_t isIncomplete = False;
spinImageIsIncomplete(hResultImage, &isIncomplete);

// Release image
spinImageRelease(hResultImage);

spinCameraEndAcquisition(hCam);

Error Handling

Every C API function returns spinError. Always check return codes:

spinError err = spinCameraInit(hCam);
if (err != SPINNAKER_ERR_SUCCESS)
{
    printf("Camera init failed: %d\n", err);
    return -1;
}

Logging

// Spinnaker C API logging uses the same five levels as C++:
// Error, Warn, Notice, Info, Debug
// Logs are saved to C:\ProgramData\Spinnaker\Logs
// See src/Logging_C/Logging_C.c for a full example

Design Conventions

Understanding these conventions is essential before using the C API — they apply uniformly across all functions.

Handle Lifecycle

All SDK objects are opaque handles that must be explicitly created and destroyed:

spinCamera hCamera = NULL;

/* Acquire handle */
spinSystemGetCameras(hSystem, &hCameraList);
spinCameraListGet(hCameraList, 0, &hCamera);
spinCameraInit(hCamera);

/* ... use camera ... */

/* Release in reverse order */
spinCameraDeInit(hCamera);
spinCameraRelease(hCamera);
spinCameraListClear(hCameraList);
spinCameraListDestroy(hCameraList);

Always release in reverse acquisition order

Releasing handles out of order or failing to release them will cause native resource leaks that persist for the process lifetime.

Error Handling

Every function returns spinError — always check it:

spinError err = SPINNAKER_ERR_SUCCESS;

err = spinCameraBeginAcquisition(hCamera);
if (err != SPINNAKER_ERR_SUCCESS) {
    char errMsg[MAX_BUFF_LEN];
    size_t lenMsg = MAX_BUFF_LEN;
    spinErrorGetLastMessage(errMsg, &lenMsg);
    fprintf(stderr, "BeginAcquisition failed: %s\n", errMsg);
    return err;
}

Error Macro

Consider wrapping the check in a macro for cleaner call sites:

    #define SPINNAKER_CHECK(call)                          \
        do {                                               \
            spinError _err = (call);                       \
            if (_err != SPINNAKER_ERR_SUCCESS) {           \
                fprintf(stderr, "Error %d at %s:%d\n",    \
                    _err, __FILE__, __LINE__);             \
                return _err;                               \
            }                                             \
        } while(0)

    /* Usage */
    SPINNAKER_CHECK(spinCameraBeginAcquisition(hCamera));

String & Buffer Pattern

Functions that return strings follow a two-call pattern:

/* First call: get required buffer size */
size_t len = 0;
spinCameraGetDeviceSerialNumber(hCamera, NULL, &len);

/* Second call: fill the buffer */
char serial[len];
spinCameraGetDeviceSerialNumber(hCamera, serial, &len);

Quick Reference

System & Discovery

Function Description
spinSystemGetInstance() Obtain the system singleton
spinSystemReleaseInstance() Release the system singleton
spinSystemGetCameras() Enumerate connected cameras
spinSystemGetLibraryVersion() Query SDK version at runtime

Camera Lifecycle

Function Description
spinCameraInit() Initialize a camera handle
spinCameraDeInit() De-initialize a camera handle
spinCameraRelease() Release handle back to the system
spinCameraBeginAcquisition() Start image acquisition
spinCameraEndAcquisition() Stop image acquisition

Image Handling

Function Description
spinCameraGetNextImageEx() Retrieve next image with timeout
spinImageIsIncomplete() Check for incomplete transfer
spinImageGetData() Access raw pixel buffer
spinImageGetWidth() Get image width in pixels
spinImageGetHeight() Get image height in pixels
spinImageGetPixelFormat() Get current pixel format
spinImageRelease() Release image back to buffer pool

Node Map & Configuration

Function Description
spinCameraGetNodeMap() Access GenICam node map
spinCameraGetTLDeviceNodeMap() Access transport layer device node map
spinCameraGetTLStreamNodeMap() Access transport layer stream node map
spinNodeMapGetNode() Retrieve a node by name
spinIntegerGetValue() Read an integer node value
spinIntegerSetValue() Write an integer node value
spinEnumerationSetEnumValue() Set an enumeration node
spinBooleanGetValue() Read a boolean node value

Camera List

Function Description
spinCameraListCreateEmpty() Create an empty camera list
spinCameraListDestroy() Destroy a camera list
spinCameraListClear() Clear all entries from a list
spinCameraListGetSize() Get number of cameras in list
spinCameraListGet() Get camera handle by index

Error Handling

Function Description
spinErrorGetLastMessage() Get last error message string
spinErrorGetLastFullMessage() Get full error details
spinErrorGetLastFileName() Get source file of last error
spinErrorGetLastFunctionName() Get function name of last error
spinErrorGetLastLineNumber() Get line number of last error

Error Code Reference

Code Value Meaning
SPINNAKER_ERR_SUCCESS 0 Operation succeeded
SPINNAKER_ERR_ERROR -1001 Generic error
SPINNAKER_ERR_NOT_INITIALIZED -1002 System not initialized
SPINNAKER_ERR_NOT_IMPLEMENTED -1003 Feature not implemented
SPINNAKER_ERR_RESOURCE_IN_USE -1004 Resource already in use
SPINNAKER_ERR_ACCESS_DENIED -1005 Insufficient permissions
SPINNAKER_ERR_INVALID_HANDLE -1006 NULL or invalid handle
SPINNAKER_ERR_INVALID_ID -1007 Invalid node or camera ID
SPINNAKER_ERR_NO_DATA -1008 No data available
SPINNAKER_ERR_INVALID_PARAMETER -1009 Bad argument value
SPINNAKER_ERR_IO -1010 I/O failure
SPINNAKER_ERR_TIMEOUT -1011 Operation timed out
SPINNAKER_ERR_ABORT -1012 Operation aborted
SPINNAKER_ERR_INVALID_BUFFER -1013 Buffer too small or NULL
SPINNAKER_ERR_NOT_AVAILABLE -1014 Feature not available on device

Known Issues & Limitations

No Exception Safety

The C API uses error codes exclusively. There is no mechanism to catch unhandled errors propagated from the underlying C++ layer. Always check every return value.

Buffer Ownership

Buffers returned by spinImageGetData() are owned by the SDK. Do not free() them — call spinImageRelease() to return the buffer to the acquisition pool.


Further Reading