Logging_C¶
Logging_C.c shows how create and use logging events. It relies on information provided in the Enumeration_C, Acquisition_C, and NodeMapInfo_C examples.
//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR).
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================
/**
* @example Logging_C.c
*
* @brief Logging_C.c shows how create and use logging events. It relies on
* information provided in the Enumeration_C, Acquisition_C, and NodeMapInfo_C
* examples.
*
* It can also be helpful to familiarize yourself with the NodeMapCallback_C
* example, as nodemap callbacks follow the same general procedure as
* events, but with a few less steps.
*
* Events generally require a class to be defined as an event handler; however,
* because C is not an object-oriented language, a pseudo-class is created
* using a function and a struct whereby the function acts as the event
* handler method and the struct acts as its properties.
*
* Please leave us feedback at: https://www.surveymonkey.com/r/TDYMVAPI
* More source code examples at: https://github.com/Teledyne-MV/Spinnaker-Examples
* Need help? Check out our forum at: https://teledynevisionsolutions.zendesk.com/hc/en-us/community/topics
*/
#include "SpinnakerC.h"
#include "stdio.h"
#include "string.h"
// This macro helps with C-strings.
#define MAX_BUFF_LEN 256
char lastErrorMessage[MAX_BUFF_LEN];
size_t lenLastErrorMessage = MAX_BUFF_LEN;
// Helper for getting error messages
char* GetLastErrorMessage()
{
// Note: lastErrorMessage is shared across multiple threads; a different thread could overwrite the last error
// message before this function is called to grab the latest message
spinErrorGetLastMessage(lastErrorMessage, &lenLastErrorMessage);
return lastErrorMessage;
}
// Define callback priority threshold; please see documentation for additional
// information on logging level philosophy.
const spinnakerLogLevel k_loggingLevel = SPINNAKER_LOG_LEVEL_DEBUG;
// This function represents what would be the method of a device event handler.
// Although it may not be immediately evident here, this example demonstrates
// the use of an empty void pointer. Also, notice that the function signature
// must match this exactly for the function to be accepted when creating the
// event.
void onLogEvent(const spinLogEventData hEventData, void* pUserData)
{
spinError err = SPINNAKER_ERR_SUCCESS;
printf("--------Log Event Received----------\n");
//
// Retrieve string log event data (category name)
//
// *** NOTES ***
// Log data is retrieved by using log event data handle in the signature.
// Most log data is of type string, needing a character array for the
// string and an integer for the number of characters.
//
char categoryName[MAX_BUFF_LEN];
size_t lenCategoryName = MAX_BUFF_LEN;
printf("Category: ");
err = spinLogDataGetCategoryName(hEventData, categoryName, &lenCategoryName);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unknown - error: %s [%d]\n\n", GetLastErrorMessage(), err);
}
else
{
printf("%s\n", categoryName);
}
//
// Retrieve integer log event data (priority)
//
// *** NOTES ***
// Not all log event data is of type string. For instance, priority delivers
// an integer.
//
int64_t priority = 0;
printf("Priority: ");
err = spinLogDataGetPriority(hEventData, &priority);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unknown - error: %s [%d]\n\n", GetLastErrorMessage(), err);
}
else
{
printf("%s\n", categoryName);
}
// Retrieve string log event data (priority name)
char priorityName[MAX_BUFF_LEN];
size_t lenPriorityName = MAX_BUFF_LEN;
printf("Priority name: ");
err = spinLogDataGetPriorityName(hEventData, priorityName, &lenPriorityName);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unknown - error: %s [%d]\n\n", GetLastErrorMessage(), err);
}
else
{
printf("%s\n", priorityName);
}
// Retrieve string log event data (timestamp)
char timestamp[MAX_BUFF_LEN];
size_t lenTimestamp = MAX_BUFF_LEN;
printf("Timestamp: ");
err = spinLogDataGetTimestamp(hEventData, timestamp, &lenTimestamp);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unknown - error: %s [%d]\n\n", GetLastErrorMessage(), err);
}
else
{
printf("%s\n", timestamp);
}
// Retrieve string log event data (NDC)
char NDC[MAX_BUFF_LEN];
size_t lenNDC = MAX_BUFF_LEN;
printf("NDC: ");
err = spinLogDataGetNDC(hEventData, NDC, &lenNDC);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unknown - error: %s [%d]\n\n", GetLastErrorMessage(), err);
}
else
{
printf("%s\n", NDC);
}
// Retrieve string log event data (thread name)
char threadName[MAX_BUFF_LEN];
size_t lenThreadName = MAX_BUFF_LEN;
printf("Thread name: ");
err = spinLogDataGetThreadName(hEventData, threadName, &lenThreadName);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unknown - error: %s [%d]\n\n", GetLastErrorMessage(), err);
}
else
{
printf("%s\n", threadName);
}
// Retrieve string log event data (log message)
char logMessage[MAX_BUFF_LEN];
size_t lenLogMessage = MAX_BUFF_LEN;
printf("Log message: ");
err = spinLogDataGetLogMessage(hEventData, logMessage, &lenLogMessage);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unknown - error: %s [%d]\n\n", GetLastErrorMessage(), err);
}
else
{
printf("%s\n", logMessage);
}
printf("------------------------------------\n\n");
}
// Example entry point; notice the volume of data that the logging event handler
// prints out on debug despite the fact that very little really happens in this
// example. Because of this, it may be better to have the logger set to lower
// level in order to provide a more concise, focussed log.
int main(/*int argc, char** argv*/)
{
spinError err = SPINNAKER_ERR_SUCCESS;
// Print application build information
printf("Application build date: %s %s \n\n", __DATE__, __TIME__);
// Retrieve singleton reference to system object
spinSystem hSystem = NULL;
err = spinSystemGetInstance(&hSystem);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to retrieve system instance. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
// Print out current library version
spinLibraryVersion hLibraryVersion;
spinSystemGetLibraryVersion(hSystem, &hLibraryVersion);
printf(
"Spinnaker library version: %d.%d.%d.%d\n\n",
hLibraryVersion.major,
hLibraryVersion.minor,
hLibraryVersion.type,
hLibraryVersion.build);
//
// Create logging event handler
//
// *** NOTES ***
// Logging event handlers need to be created prior to registration; however, the
// logging level may be set after registration.
//
// *** LATER ***
// In Spinnaker C, every event handler that is created must be destroyed to avoid
// memory leaks.
//
spinLogEventHandler logEventHandler = NULL;
err = spinLogEventHandlerCreate(&logEventHandler, onLogEvent, NULL);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to create log event. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
//
// Register logging event handler
//
// *** NOTES ***
// Logging event handlers are registered to the system. Take note that a logging
// event handler is very verbose when the logging level is set to debug.
//
// *** LATER ***
// Logging event handlers must be unregistered manually. This must be done prior to
// releasing the system and while the device event handlers are still in scope.
//
err = spinSystemRegisterLogEventHandler(hSystem, logEventHandler);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to register log event. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
//
// Set callback priority level
//
// *** NOTES ***
// Please see documentation for information on the logging philosophies of
// the Spinnaker SDK.
//
err = spinSystemSetLoggingLevel(hSystem, k_loggingLevel);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to set logging level. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
// Retrieve list of cameras from the system
spinCameraList hCameraList = NULL;
size_t numCameras = 0;
err = spinCameraListCreateEmpty(&hCameraList);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to retrieve camera list. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
err = spinSystemGetCameras(hSystem, hCameraList);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to retrieve camera list. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
err = spinCameraListGetSize(hCameraList, &numCameras);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to retrieve number of cameras. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
printf("Number of cameras detected: %u\n\n", (unsigned int)numCameras);
// Clear and destroy camera list before releasing system
err = spinCameraListClear(hCameraList);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to clear camera list. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
err = spinCameraListDestroy(hCameraList);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to destroy camera list. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
//
// Unregister logging event handler
//
// *** NOTES ***
// Logging event handlers may be unregistered altogether or individually. It is
// important to unregister all logging event handlers from the system.
//
err = spinSystemUnregisterAllLogEventHandlers(hSystem);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to unregister log event. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
//
// Destroy event handlers
//
// *** NOTES ***
// Event handlers must be destroyed in order to avoid memory leaks.
//
err = spinLogEventHandlerDestroy(logEventHandler);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to destroy log event. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
// Release system
err = spinSystemReleaseInstance(hSystem);
if (err != SPINNAKER_ERR_SUCCESS)
{
printf("Unable to release system instance. Aborting with error: %s [%d]\n\n", GetLastErrorMessage(), err);
return err;
}
printf("\nDone! Press Enter to exit...\n");
getchar();
return err;
}