### Build and Run C Examples Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/Examples/C/README.md Commands to build and run the C examples. Requires the missing library file to be present. Setup is done once, then build and run on macOS or Windows. ```bash cd # Setup (only needs to be done once) mkdir build cd build cmake .. # Build cmake --build . --target C-Examples # Run on macOS ../build/Examples/C/C-Examples # Run on Windows ..\build\Examples\C\Debug\C-Examples.exe ``` -------------------------------- ### Build and Run C++ Examples with CMake Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/Examples/Cpp/README.md Use these commands to build and run the C++ examples. First, set up the build directory and run cmake. Then build the target 'Cpp-Examples' and run the executable. This assumes the missing library file is present. ```bash cd # Setup (only needs to be done once) mkdir build cd build cmake .. # Build cmake --build . --target Cpp-Examples # Run on macOS ../build/Examples/Cpp/Cpp-Examples # Run on Windows ..\build\Examples\Cpp\Debug\Cpp-Examples.exe ``` -------------------------------- ### CMakeLists.txt for C examples Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/Examples/C/CMakeLists.txt CMake configuration for building the C examples. It recursively collects all .c files, creates an executable named C-Examples, adds the x-IMU3-API/C directory to the include path, and links Cocoa and IOKit frameworks on Apple platforms. ```cmake file(GLOB_RECURSE files "*.c") add_executable(C-Examples ${files}) target_include_directories(C-Examples PUBLIC "../../x-IMU3-API/C") if (APPLE) target_link_libraries(C-Examples PRIVATE "-framework Cocoa" "-framework IOKit") endif () ``` -------------------------------- ### Compile Rust-API from command line Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-API/Rust/target/release/README.md Run these commands from the repository root to build the Rust API in release mode. The build produces the required library file. ```bash cd /x-IMU3-API/Rust cargo build --release ``` -------------------------------- ### Collect asset files and create binary data target Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Globs font, image, firmware, and OpenGL asset files, then creates a JUCE binary data target embedding these resources into the application. ```cmake FILE(GLOB_RECURSE FONT_FILES "Fonts/*.*") FILE(GLOB_RECURSE IMAGE_FILES "Images/*.*") FILE(GLOB FIRMWARE_FILE "Source/Firmware/*.hex") FILE(GLOB_RECURSE OPEN_GL_FILES "Source/OpenGL/Assets/*.*") juce_add_binary_data(x-IMU3-GUI-AppData SOURCES "Source/DeviceSettings/DeviceSettings.xml" "Source/Dialogs/CommandKeys.xml" ${FONT_FILES} ${IMAGE_FILES} ${FIRMWARE_FILE} ${OPEN_GL_FILES}) ``` -------------------------------- ### Link libraries and set include directories Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Links the target with app data, JUCE OpenGL, FreeType, and GLM libraries, and adds include directories for Source, API, FreeType, and Bootloader. Adds a dependency on FreeType. ```cmake target_link_libraries(x-IMU3-GUI PRIVATE x-IMU3-GUI-AppData juce::juce_opengl "${FREETYPE_LIBRARIES}" glm::glm PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_lto_flags juce::juce_recommended_warning_flags) target_include_directories(x-IMU3-GUI PRIVATE "Source" "../x-IMU3-API/Cpp" "${FREETYPE_INCLUDE_DIRS}" "../x-IMU3-Bootloader") add_dependencies(x-IMU3-GUI freetype) ``` -------------------------------- ### Fetch and configure JUCE dependency Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Fetches JUCE 8.0.12 from GitHub using FetchContent with shallow clone and progress output. Disables FetchContent quiet mode to show progress. ```cmake include(FetchContent) Set(FETCHCONTENT_QUIET FALSE) FetchContent_Declare( JUCE GIT_REPOSITORY https://github.com/juce-framework/JUCE.git GIT_TAG 8.0.12 GIT_PROGRESS TRUE GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(JUCE) ``` -------------------------------- ### Define x-IMU3-GUI executable target Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Creates a JUCE GUI application target named x-IMU3-GUI with specified icon, product name, bundle ID, and company metadata. The product name differs from target name and is used for the final executable. ```cmake juce_add_gui_app(x-IMU3-GUI ICON_BIG "Images/xio_icon.png" PRODUCT_NAME "x-IMU3 GUI" # The name of the final executable, which can differ from the target name BUNDLE_ID "uk.co.x-io.x-IMU3-GUI" COMPANY_COPYRIGHT "Copyright (c) 2024 x-io Technologies Limited" COMPANY_NAME "x-io Technologies Limited" COMPANY_WEBSITE "www.x-io.co.uk" COMPANY_EMAIL "info@x-io.co.uk") ``` -------------------------------- ### Fetch and configure GLM dependency Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Fetches GLM 1.0.3 from GitHub using FetchContent with shallow clone and progress output. ```cmake FetchContent_Declare( glm GIT_REPOSITORY https://github.com/g-truc/glm GIT_TAG 1.0.3 GIT_PROGRESS TRUE GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(glm) ``` -------------------------------- ### Set build timestamp and commit SHA definitions Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Generates build date and commit SHA using git, then defines compile definitions for the target including JUCE settings and build metadata. ```cmake string(TIMESTAMP BUILD_DATE UTC) execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD OUTPUT_VARIABLE COMMIT_SHA OUTPUT_STRIP_TRAILING_WHITESPACE) target_compile_definitions(x-IMU3-GUI PRIVATE JUCE_WEB_BROWSER=0 JUCE_USE_CURL=0 JUCE_APPLICATION_NAME_STRING="$" JUCE_APPLICATION_VERSION_STRING="$" GLM_FORCE_SIZE_T_LENGTH # Resolves signed conversion warning on Ubuntu BUILD_DATE="${BUILD_DATE}" COMMIT_SHA="${COMMIT_SHA}") ``` -------------------------------- ### Fetch and configure FreeType dependency Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Fetches FreeType 2.14.1 from GitLab, disables system packages for ZLIB, PNG, BZip2, BrotliDec, and HarfBuzz to avoid conflicts. Sets up FreeType include and library variables, then finds the built package. ```cmake Set(CMAKE_DISABLE_FIND_PACKAGE_ZLIB TRUE) Set(CMAKE_DISABLE_FIND_PACKAGE_PNG TRUE) Set(CMAKE_DISABLE_FIND_PACKAGE_BZip2 TRUE) Set(CMAKE_DISABLE_FIND_PACKAGE_BrotliDec TRUE) Set(CMAKE_DISABLE_FIND_PACKAGE_HarfBuzz TRUE) FetchContent_Declare( freetype GIT_REPOSITORY https://gitlab.freedesktop.org/freetype/freetype.git GIT_TAG VER-2-14-1 GIT_PROGRESS TRUE GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(freetype) FetchContent_GetProperties(freetype SOURCE_DIR FREETYPE_SRC_DIR) set(FREETYPE_INCLUDE_DIRS ${FREETYPE_SRC_DIR}/include) set(FREETYPE_LIBRARY freetype) set(FREETYPE_LIBRARIES freetype) find_package(Freetype REQUIRED CONFIGS "freetype-config-version.cmake" PATHS "${FREETYPE_SRC_DIR}/../freetype-build/" NO_DEFAULT_PATH) ``` -------------------------------- ### C++ graph window constructor template with placeholders Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/Source/Windows/Graphs/template_cpp.txt Template for a JUCE-based graph window constructor and destructor. The constructor passes parameters to the base GraphWindow class and includes placeholders for generated callback implementations. The destructor removes all callbacks stored in callbackIds from the connection. ```cpp #include "ConnectionPanel/ConnectionPanel.h" #include "$name$GraphWindow.h" $name$GraphWindow::$name$GraphWindow(const juce::ValueTree &windowLayout_, const juce::Identifier &type_, ConnectionPanel &connectionPanel_, OpenGLRenderer &openGLRenderer) : GraphWindow(windowLayout_, type_, connectionPanel_, openGLRenderer, "$y_axis$", $legend_strings$, $legend_colours$, $horizontal_autoscale$, $show_timestamp$) { $callback_implementations$ } $name$GraphWindow::~$name$GraphWindow() { for (const auto callbackId: callbackIds) { connectionPanel.getConnection()->removeCallback(callbackId); } } ``` -------------------------------- ### Set C++ standard to 20 Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Sets the C++ standard for the x-IMU3-GUI target to C++20. ```cmake set_property(TARGET x-IMU3-GUI PROPERTY CXX_STANDARD 20) ``` -------------------------------- ### Collect source files and add to target Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-GUI/CMakeLists.txt Globs source files recursively, adds platform-specific Mac file, and includes a shared API source file. On Apple platforms, adds Source/UIUtilsMac.mm. ```cmake FILE(GLOB_RECURSE CPP_FILES "Source/*.cpp") target_sources(x-IMU3-GUI PRIVATE ${CPP_FILES}) if (APPLE) target_sources(x-IMU3-GUI PRIVATE Source/UIUtilsMac.mm) endif () target_sources(x-IMU3-GUI PRIVATE ../x-IMU3-API/Cpp/ConnectionConfig.cpp) ``` -------------------------------- ### C Header Template for XIMU3 Message Wrapper Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-API/Python/ximu3/src/DataMessages/TemplateCharArray.txt This is a C header template for a Python extension that wraps a XIMU3 message type. It defines the object structure, getters for timestamp, string, and bytes properties, and a callback function that acquires the GIL to call a Python function. The template uses placeholders like $name_macro_case$ and $name_pascal_case$ that would be replaced in actual usage. ```C #ifndef $name_macro_case$_MESSAGE_H #define $name_macro_case$_MESSAGE_H #include "../../../../C/Ximu3.h" #include typedef struct { PyObject_HEAD XIMU3_$name_pascal_case$Message wrapped; } $name_pascal_case$Message; static void $name_snake_case$_message_free($name_pascal_case$Message *self) { Py_TYPE(self)->tp_free(self); } static PyObject *$name_snake_case$_message_str($name_pascal_case$Message *self) { const char *const string = XIMU3_$name_snake_case$_message_to_string(self->wrapped); return PyUnicode_FromString(string); } static PyObject *$name_snake_case$_message_get_timestamp($name_pascal_case$Message *self, PyObject *args) { return PyLong_FromUnsignedLongLong((unsigned long long) self->wrapped.timestamp); } static PyObject *$name_snake_case$_message_get_string($name_pascal_case$Message *self, PyObject *args) { return PyUnicode_FromString(self->wrapped.char_array); } static PyObject *$name_snake_case$_message_get_bytes($name_pascal_case$Message *self, PyObject *args) { return PyByteArray_FromStringAndSize(self->wrapped.char_array, (Py_ssize_t) self->wrapped.number_of_bytes); } static PyGetSetDef $name_snake_case$_message_get_set[] = { {"timestamp", (getter) $name_snake_case$_message_get_timestamp, NULL, "", NULL}, {"string", (getter) $name_snake_case$_message_get_string, NULL, "", NULL}, {"bytes", (getter) $name_snake_case$_message_get_bytes, NULL, "", NULL}, {NULL} /* sentinel */ }; static PyTypeObject $name_snake_case$_message_object = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "ximu3.$name_pascal_case$Message", .tp_basicsize = sizeof($name_pascal_case$Message), .tp_dealloc = (destructor) $name_snake_case$_message_free, .tp_str = (reprfunc) $name_snake_case$_message_str, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_getset = $name_snake_case$_message_get_set, }; static PyObject *$name_snake_case$_message_from(const XIMU3_$name_pascal_case$Message *const message) { $name_pascal_case$Message *const self = ($name_pascal_case$Message *) $name_snake_case$_message_object.tp_alloc(&$name_snake_case$_message_object, 0); if (self == NULL) { return NULL; } self->wrapped = *message; return (PyObject *) self; } static void $name_snake_case$_message_callback(XIMU3_$name_pascal_case$Message data, void *context) { PyObject *object = NULL; PyObject *tuple = NULL; PyObject *result = NULL; const PyGILState_STATE state = PyGILState_Ensure(); object = $name_snake_case$_message_from(&data); if (object == NULL) { PyErr_Print(); goto cleanup; } tuple = PyTuple_Pack(1, object); if (tuple == NULL) { PyErr_Print(); goto cleanup; } result = PyObject_CallObject((PyObject *) context, tuple); if (result == NULL) { PyErr_Print(); } cleanup: Py_XDECREF(object); Py_XDECREF(tuple); Py_XDECREF(result); PyGILState_Release(state); } #endif ``` -------------------------------- ### Rust float data message template implementation Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-API/Rust/src/data_messages/template_float.txt Template for a float data message in the x-IMU3 Rust API. Implements DataMessage with ASCII/binary parsing, CSV methods, and Display. Uses placeholders like $name_pascal_case$ and $arguments_*$ to be replaced per message. Includes unsafe binary parsing with length check. ```Rust use crate::data_messages::*; use crate::receive_error::*; use std::fmt; use std::mem::size_of; #[repr(C)] #[derive(Clone, Copy)] pub struct $name_pascal_case$Message { pub timestamp: u64, $arguments_struct_declare$ } impl Default for $name_pascal_case$Message { fn default() -> Self { Self { timestamp: 0, $arguments_struct_default$ } } } impl DataMessage for $name_pascal_case$Message { fn get_ascii_id() -> u8 { b'$ascii_id$' } fn parse_ascii(message: &str) -> Result { match scan_fmt!(message, "{},{d},$arguments_scan_fmt$\n", char, u64, $arguments_types$) { Ok((_, timestamp, $arguments_scan_result$)) => Ok(Self { timestamp, $arguments_struct_asign$ }), Err(_) => Err(ReceiveError::UnableToParseAsciiMessage), } } fn parse_binary(message: &[u8]) -> Result { #[repr(C, packed)] struct BinaryMessage { _id: u8, timestamp: u64, $arguments_packed_struct$ _termination: u8, } if message.len() != size_of::() { return Err(ReceiveError::InvalidBinaryMessageLength); } let binary_message = unsafe { let ref binary_message = *(message.as_ptr() as *const BinaryMessage); binary_message }; Ok(Self { timestamp: binary_message.timestamp, $arguments_assign_struct$ }) } fn get_csv_file_name(&self) -> &'static str { "$name_pascal_case$.csv" } fn get_csv_headings(&self) -> &'static str { "Timestamp (us),$csv_headings$\n" } fn to_csv_row(&self) -> String { format!("{},$arguments_csv_format$\n", self.timestamp, $arguments_self_list$) } } impl fmt::Display for $name_pascal_case$Message { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:>8} us$arguments_string_format$", self.timestamp, $arguments_self_list$) } } ``` -------------------------------- ### C Extension Template for X-IMU3 Data Message Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-API/Python/ximu3/src/DataMessages/TemplateFloat.txt This is the complete template for generating a Python C extension for a data message type. It defines the message object, its methods, and a callback that converts C data to Python objects while managing the GIL. Placeholders are used for the message name in various cases. ```C #ifndef $name_macro_case$_MESSAGE_H #define $name_macro_case$_MESSAGE_H #include "../../../../C/Ximu3.h" #include typedef struct { PyObject_HEAD XIMU3_$name_pascal_case$Message wrapped; } $name_pascal_case$Message; static void $name_snake_case$_message_free($name_pascal_case$Message *self) { Py_TYPE(self)->tp_free(self); } static PyObject *$name_snake_case$_message_str($name_pascal_case$Message *self) { const char *const string = XIMU3_$name_snake_case$_message_to_string(self->wrapped); return PyUnicode_FromString(string); } $get_functions$ static PyGetSetDef $name_snake_case$_message_get_set[] = { $get_set_members$ {NULL} /* sentinel */ }; static PyTypeObject $name_snake_case$_message_object = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "ximu3.$name_pascal_case$Message", .tp_basicsize = sizeof($name_pascal_case$Message), .tp_dealloc = (destructor) $name_snake_case$_message_free, .tp_str = (reprfunc) $name_snake_case$_message_str, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_getset = $name_snake_case$_message_get_set, }; static PyObject *$name_snake_case$_message_from(const XIMU3_$name_pascal_case$Message *const message) { $name_pascal_case$Message *const self = ($name_pascal_case$Message *) $name_snake_case$_message_object.tp_alloc(&$name_snake_case$_message_object, 0); if (self == NULL) { return NULL; } self->wrapped = *message; return (PyObject *) self; } static void $name_snake_case$_message_callback(XIMU3_$name_pascal_case$Message data, void *context) { PyObject *object = NULL; PyObject *tuple = NULL; PyObject *result = NULL; const PyGILState_STATE state = PyGILState_Ensure(); object = $name_snake_case$_message_from(&data); if (object == NULL) { PyErr_Print(); goto cleanup; } tuple = PyTuple_Pack(1, object); if (tuple == NULL) { PyErr_Print(); goto cleanup; } result = PyObject_CallObject((PyObject *) context, tuple); if (result == NULL) { PyErr_Print(); } cleanup: Py_XDECREF(object); Py_XDECREF(tuple); Py_XDECREF(result); PyGILState_Release(state); } #endif ``` -------------------------------- ### Rust char array message template implementation Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-API/Rust/src/data_messages/template_char_array.txt Defines a Rust data message struct for char array data, including parsing from ASCII and binary formats, CSV output, and display. Uses placeholders $name_pascal_case$ and $ascii_id$ to be replaced with the specific message name and ASCII ID. ```rust use crate::data_messages::*; use crate::receive_error::*; use libc::size_t; use std::fmt; use std::mem::size_of; use std::os::raw::c_char; #[repr(C)] #[derive(Clone, Copy)] pub struct $name_pascal_case$Message { pub timestamp: u64, pub char_array: [c_char; DATA_MESSAGE_CHAR_ARRAY_SIZE], pub number_of_bytes: size_t, } impl Default for $name_pascal_case$Message { fn default() -> Self { Self { timestamp: 0, char_array: [0; DATA_MESSAGE_CHAR_ARRAY_SIZE], number_of_bytes: 0, } } } impl $name_pascal_case$Message { pub fn char_array_as_string(self) -> String { char_array_to_string(&self.char_array, self.number_of_bytes) } } impl DataMessage for $name_pascal_case$Message { fn get_ascii_id() -> u8 { b'$ascii_id$' } fn parse_ascii(message: &str) -> Result { match scan_fmt!(message, "{},{d},{[^\n]}\n", char, u64, String) { Ok((_, timestamp, string)) => { let (char_array, number_of_bytes) = string_to_char_array(string); Ok(Self { timestamp, char_array, number_of_bytes, }) } Err(_) => Err(ReceiveError::UnableToParseAsciiMessage), } } fn parse_binary(message: &[u8]) -> Result { #[repr(C, packed)] struct Header { _id: u8, timestamp: u64, } let min_message_size = size_of::
() + 1; // include termination byte if message.len() < min_message_size { return Err(ReceiveError::InvalidBinaryMessageLength); } let timestamp = unsafe { let ref binary_message = *(message.as_ptr() as *const Header); binary_message.timestamp }; let (char_array, number_of_bytes) = slice_to_char_array(&message[size_of::
()..(message.len() - 1)]); // exclude termination byte Ok($name_pascal_case$Message { timestamp, char_array, number_of_bytes, }) } fn get_csv_file_name(&self) -> &'static str { "$name_pascal_case$.csv" } fn get_csv_headings(&self) -> &'static str { "Timestamp (us),String\n" } fn to_csv_row(&self) -> String { format!("{},{}\n", self.timestamp, char_array_to_string(&self.char_array, self.number_of_bytes)) } } impl fmt::Display for $name_pascal_case$Message { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:>8} us \"{}\"", self.timestamp, char_array_to_string(&self.char_array, self.number_of_bytes)) } } ``` -------------------------------- ### C Extension Template for XIMU3 Message Python Type Source: https://github.com/xiotechnologies/x-imu3-software/blob/main/x-IMU3-API/Python/ximu3/src/DataMessages/TemplateFloatMethods.txt Template for generating a Python C extension type for a XIMU3 message. It defines the struct, free/str functions, getset and method tables, the type object, a from function to wrap the C message, and a callback that acquires the GIL and invokes a Python callable. Placeholders like $name_snake_case$ and $get_functions$ are meant to be replaced by the code generator. ```c #ifndef $name_macro_case$_MESSAGE_H #define $name_macro_case$_MESSAGE_H #include "../../../../C/Ximu3.h" #include typedef struct { PyObject_HEAD XIMU3_$name_pascal_case$Message wrapped; } $name_pascal_case$Message; static void $name_snake_case$_message_free($name_pascal_case$Message *self) { Py_TYPE(self)->tp_free(self); } static PyObject *$name_snake_case$_message_str($name_pascal_case$Message *self) { const char *const string = XIMU3_$name_snake_case$_message_to_string(self->wrapped); return PyUnicode_FromString(string); } $get_functions$ $method_functions$ static PyGetSetDef $name_snake_case$_message_get_set[] = { $get_set_members$ {NULL} /* sentinel */ }; static PyMethodDef $name_snake_case$_message_methods[] = { $method_members$ {NULL} /* sentinel */ }; static PyTypeObject $name_snake_case$_message_object = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "ximu3.$name_pascal_case$Message", .tp_basicsize = sizeof($name_pascal_case$Message), .tp_dealloc = (destructor) $name_snake_case$_message_free, .tp_str = (reprfunc) $name_snake_case$_message_str, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_getset = $name_snake_case$_message_get_set, .tp_methods = $name_snake_case$_message_methods, }; static PyObject *$name_snake_case$_message_from(const XIMU3_$name_pascal_case$Message *const message) { $name_pascal_case$Message *const self = ($name_pascal_case$Message *) $name_snake_case$_message_object.tp_alloc(&$name_snake_case$_message_object, 0); if (self == NULL) { return NULL; } self->wrapped = *message; return (PyObject *) self; } static void $name_snake_case$_message_callback(XIMU3_$name_pascal_case$Message data, void *context) { PyObject *object = NULL; PyObject *tuple = NULL; PyObject *result = NULL; const PyGILState_STATE state = PyGILState_Ensure(); object = $name_snake_case$_message_from(&data); if (object == NULL) { PyErr_Print(); goto cleanup; } tuple = PyTuple_Pack(1, object); if (tuple == NULL) { PyErr_Print(); goto cleanup; } result = PyObject_CallObject((PyObject *) context, tuple); if (result == NULL) { PyErr_Print(); } cleanup: Py_XDECREF(object); Py_XDECREF(tuple); Py_XDECREF(result); PyGILState_Release(state); } #endif ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.