Leap Motion开发(一)下载安装以及环境配置

本开发同样适用于Ultraleap Stereo IR170

1、官网下载SDK

SDK
API
值得说明的是,IR170这块开发板提供的API是基于C语言的,与LeapMotion提供的基于C++的API不同,但配置过程基本相同。

2、配置环境

添加附加依赖项

项目-属性-连接器-输入-附加依赖项添加LeapC.lib

添加包含目录和库目录

包含目录: D:\CODING\LeapCEnv\LeapCEnv\LeapSDK\include
库目录:D:\CODING\LeapCEnv\LeapCEnv\LeapSDK\lib\x64
官方提供的SDK里,LeapSDK\lib下包含x64和x86,需要在库目录里写明选用哪种架构,不然会报找不到lib的错误。

环境变量(实测不需要,暂时保留

完成以上两步,官网提供的sample就已经能跑了,但是有的教程里还是说明了要配置系统环境变量,所以在这里记录一下,如果以上两步之后还是有问题可以再试试这一步。
(1)把lib\x64文件夹下的LeapC.dll添加进环境变量,路径为:\LeapSDK\lib\x64
添加环境变量的作用是让你编译生成的EXE程序能访问到对应目录里的dll,如果不想添加进环境变量可以把dll拷贝进调试目录,直接把那些dll拷贝到EXE的目录就可以直接访问而不用添加环境变量。
(2)把lib\x64文件夹下的LeapC.dll拷贝进调试目录,路径为 \Code\Debug 和 \Code\Code\Debug
我不知道拷贝到哪一个Debug目录生效,可以自行排查一下。

C++调用C代码

需要注意的是,在调用Leap Motion官方提供的源码时,比如如下的ExampleConnection.h,其是C的代码,如果我们自己写的程序是CPP的,则需要在被调用C头文件中添加条件编译语句如下:

#ifdef __cplusplus

extern "C"{
    
    

#endif

// C代码

#ifdef __cplusplus

};

#endif


Main.cpp

#include "ExampleConnection.h"
int64_t lastDrawnFrameId = 0;
volatile int64_t newestFrameId = 0;

void OnFrame(const LEAP_TRACKING_EVENT* frame) {
    
    
	newestFrameId = (int64_t)frame->tracking_frame_id;
}
void main(){
    
    
	ConnectionCallbacks.on_frame = OnFrame;
	OpenConnection();
	CloseConnection();
}

ExampleConnection.h

#ifdef __cplusplus
extern "C"{
    
    
#endif

#ifndef ExampleConnection_h
#define ExampleConnection_h

#include "LeapC.h"

// blabla

#ifdef __cplusplus
};
#endif

不然就会在链接时,报无法解析的外部符号的错误

3、测试

在工程中添加以下三段代码:

CallbackSample.c

#undef __cplusplus

#include <stdio.h>
#include <stdlib.h>
#include "LeapC.h"
#include "ExampleConnection.h"

static LEAP_CONNECTION* connectionHandle;

 /** Callback for when the connection opens. */
 static void OnConnect() {
    
    
   printf("Connected.\n");

}

 /** Callback for when a device is found. */
 static void OnDevice(const LEAP_DEVICE_INFO *props) {
    
    
   printf("Found device %s.\n", props->serial);

}

 /** Callback for when a frame of tracking data is available. */
 static void OnFrame(const LEAP_TRACKING_EVENT *frame) {
    
    
   printf("Frame %lli with %i hands.\n", (long long int)frame->info.frame_id, frame->nHands);

   for (uint32_t h = 0; h < frame->nHands; h++) {
    
    
     LEAP_HAND* hand = &frame->pHands[h];
     printf("    Hand id %i is a %s hand with position (%f, %f, %f).\n",
                 hand->id,
                 (hand->type == eLeapHandType_Left ? "left" : "right"),
                 hand->palm.position.x,
                 hand->palm.position.y,
                 hand->palm.position.z);

}

}

 static void OnImage(const LEAP_IMAGE_EVENT *image) {
    
    
   printf("Image %lli  => Left: %d x %d (bpp=%d), Right: %d x %d (bpp=%d)\n",
       (long long int)image->info.frame_id,
       image->image[0].properties.width, image->image[0].properties.height, image->image[0].properties.bpp * 8,
       image->image[1].properties.width, image->image[1].properties.height, image->image[1].properties.bpp * 8);

}

static void OnLogMessage(const eLeapLogSeverity severity, const int64_t timestamp,
                         const char* message) {
    
    
  const char* severity_str;
  switch (severity) {
    
    
    case eLeapLogSeverity_Critical:
      severity_str = "Critical";
      break;
    case eLeapLogSeverity_Warning:
      severity_str = "Warning";
      break;
    case eLeapLogSeverity_Information:
      severity_str = "Info";
      break;
    default:
      severity_str = "";
      break;

}
   printf("[%s][%lli] %s\n", severity_str, (long long int)timestamp, message);

}

 static void* allocate(uint32_t size, eLeapAllocatorType typeHint, void* state) {
    
    
   void* ptr = malloc(size);
   return ptr;

}

 static void deallocate(void* ptr, void* state) {
    
    
   if (!ptr)
     return;
   free(ptr);

}

 void OnPointMappingChange(const LEAP_POINT_MAPPING_CHANGE_EVENT *change) {
    
    
   if (!connectionHandle)
     return;

   uint64_t size = 0;
   if (LeapGetPointMappingSize(*connectionHandle, &size) != eLeapRS_Success || !size)
     return;

   LEAP_POINT_MAPPING* pointMapping = (LEAP_POINT_MAPPING*)malloc(size);
   if (!pointMapping)
     return;

   if (LeapGetPointMapping(*connectionHandle, pointMapping, &size) == eLeapRS_Success &&
       pointMapping->nPoints > 0) {
    
    
     printf("Managing %u points as of frame %lld at %lld\n", pointMapping->nPoints, (long long int)pointMapping->frame_id, (long long int)pointMapping->timestamp);

}
  free(pointMapping);

}

void OnHeadPose(const LEAP_HEAD_POSE_EVENT *event) {
    
    
  printf("Head pose:\n");
  printf("    Head position (%f, %f, %f).\n",
    event->head_position.x,
    event->head_position.y,
    event->head_position.z);
  printf("    Head orientation (%f, %f, %f, %f).\n",
    event->head_orientation.w,
     event->head_orientation.x,
     event->head_orientation.y,
     event->head_orientation.z);

}

 int main(int argc, char** argv) {
    
    
   //Set callback function pointers
   ConnectionCallbacks.on_connection = &OnConnect;
   ConnectionCallbacks.on_device_found = &OnDevice;
   ConnectionCallbacks.on_frame = &OnFrame;
   ConnectionCallbacks.on_image = &OnImage;
   ConnectionCallbacks.on_point_mapping_change = &OnPointMappingChange;
   ConnectionCallbacks.on_log_message = &OnLogMessage;
   ConnectionCallbacks.on_head_pose = &OnHeadPose;

   connectionHandle = OpenConnection();
   {
    
    
     LEAP_ALLOCATOR allocator = {
    
     allocate, deallocate, NULL };
     LeapSetAllocator(*connectionHandle, &allocator);
   }
   LeapSetPolicyFlags(*connectionHandle, eLeapPolicyFlag_Images | eLeapPolicyFlag_MapPoints, 0);

   printf("Press Enter to exit program.\n");
   getchar();

   DestroyConnection();

   return 0;

}
 //End-of-Sample.c

ExampleConnection.h

#ifndef ExampleConnection_h
#define ExampleConnection_h

#include "LeapC.h"

/* Client functions */
LEAP_CONNECTION* OpenConnection();
void CloseConnection();
void DestroyConnection();
 LEAP_TRACKING_EVENT* GetFrame(); //Used in polling example
 LEAP_DEVICE_INFO* GetDeviceProperties(); //Used in polling example
 const char* ResultString(eLeapRS r);

 /* State */
 extern bool IsConnected;

 /* Callback function pointers */
 typedef void(*connection_callback)     ();
 typedef void(*device_callback)         (const LEAP_DEVICE_INFO *device);
 typedef void(*device_lost_callback)    ();
 typedef void(*device_failure_callback) (const eLeapDeviceStatus failure_code,
                                          const LEAP_DEVICE failed_device);
 typedef void(*policy_callback)         (const uint32_t current_policies);
 typedef void(*tracking_callback)       (const LEAP_TRACKING_EVENT *tracking_event);
 typedef void(*log_callback)            (const eLeapLogSeverity severity,
                                          const int64_t timestamp,
                                          const char* message);
 typedef void(*config_change_callback)  (const uint32_t requestID, const bool success);
 typedef void(*config_response_callback)(const uint32_t requestID, LEAP_VARIANT value);
 typedef void(*image_callback)          (const LEAP_IMAGE_EVENT *image_event);
 typedef void(*point_mapping_change_callback)(const LEAP_POINT_MAPPING_CHANGE_EVENT *point_mapping_change_event);
 typedef void(*head_pose_callback)(const LEAP_HEAD_POSE_EVENT *head_pose_event);

 struct Callbacks {
    
    
   connection_callback      on_connection;
   connection_callback      on_connection_lost;
   device_callback          on_device_found;
   device_lost_callback     on_device_lost;
   device_failure_callback  on_device_failure;
   policy_callback          on_policy;
   tracking_callback        on_frame;
   log_callback             on_log_message;
   config_change_callback   on_config_change;
   config_response_callback on_config_response;
   image_callback           on_image;
   point_mapping_change_callback on_point_mapping_change;
   head_pose_callback       on_head_pose;

};
 extern struct Callbacks ConnectionCallbacks;
 extern void millisleep(int milliseconds);
 #endif /* ExampleConnection_h */

ExampleConnection.c

#include "ExampleConnection.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if defined(_MSC_VER)
 #include <Windows.h>
 #include <process.h>
 #define LockMutex EnterCriticalSection
 #define UnlockMutex LeaveCriticalSection
#else
  #include <unistd.h>
  #include <pthread.h>
  #define LockMutex pthread_mutex_lock
  #define UnlockMutex pthread_mutex_unlock
#endif


//Forward declarations
#if defined(_MSC_VER)
static void serviceMessageLoop(void * unused);
#else
static void* serviceMessageLoop(void * unused);
#endif
static void setFrame(const LEAP_TRACKING_EVENT *frame);
static void setDevice(const LEAP_DEVICE_INFO *deviceProps);

//External state
bool IsConnected = false;

//Internal state
static volatile bool _isRunning = false;
static LEAP_CONNECTION connectionHandle = NULL;
static LEAP_TRACKING_EVENT *lastFrame = NULL;
static LEAP_DEVICE_INFO *lastDevice = NULL;

//Callback function pointers
struct Callbacks ConnectionCallbacks;

//Threading variables
#if defined(_MSC_VER)
static HANDLE pollingThread;
static CRITICAL_SECTION dataLock;
#else
static pthread_t pollingThread;
static pthread_mutex_t dataLock;
#endif

/**
 * Creates the connection handle and opens a connection to the Leap Motion
 * service. On success, creates a thread to service the LeapC message pump.
 */
LEAP_CONNECTION* OpenConnection(){
    
    
  if(_isRunning){
    
    
    return &connectionHandle;
  }
  if(connectionHandle || LeapCreateConnection(NULL, &connectionHandle) == eLeapRS_Success){
    
    
    eLeapRS result = LeapOpenConnection(connectionHandle);
    if(result == eLeapRS_Success){
    
    
      _isRunning = true;
#if defined(_MSC_VER)
      InitializeCriticalSection(&dataLock);
      pollingThread = (HANDLE)_beginthread(serviceMessageLoop, 0, NULL);
#else
      pthread_create(&pollingThread, NULL, serviceMessageLoop, NULL);
#endif
    }
  }
  return &connectionHandle;
}

void CloseConnection(){
    
    
  if(!_isRunning){
    
    
    return;
  }
  _isRunning = false;
  LeapCloseConnection(connectionHandle);
#if defined(_MSC_VER)
  WaitForSingleObject(pollingThread, INFINITE);
  CloseHandle(pollingThread);
#else
  pthread_join(pollingThread, NULL);
#endif
}

void DestroyConnection(){
    
    
  CloseConnection();
  LeapDestroyConnection(connectionHandle);
}


/** Close the connection and let message thread function end. */
void CloseConnectionHandle(LEAP_CONNECTION* connectionHandle){
    
    
  LeapDestroyConnection(*connectionHandle);
  _isRunning = false;
}

/** Called by serviceMessageLoop() when a connection event is returned by LeapPollConnection(). */
static void handleConnectionEvent(const LEAP_CONNECTION_EVENT *connection_event){
    
    
  IsConnected = true;
   if(ConnectionCallbacks.on_connection){
    
    
     ConnectionCallbacks.on_connection();
   }
 }
 
 /** Called by serviceMessageLoop() when a connection lost event is returned by LeapPollConnection(). */
 static void handleConnectionLostEvent(const LEAP_CONNECTION_LOST_EVENT *connection_lost_event){
    
    
   IsConnected = false;
   if(ConnectionCallbacks.on_connection_lost){
    
    
     ConnectionCallbacks.on_connection_lost();
   }
 }
 
 /**
  * Called by serviceMessageLoop() when a device event is returned by LeapPollConnection()
  * Demonstrates how to access device properties.
  */
 static void handleDeviceEvent(const LEAP_DEVICE_EVENT *device_event){
    
    
   LEAP_DEVICE deviceHandle;
   //Open device using LEAP_DEVICE_REF from event struct.
   eLeapRS result = LeapOpenDevice(device_event->device, &deviceHandle);
   if(result != eLeapRS_Success){
    
    
     printf("Could not open device %s.\n", ResultString(result));
     return;
   }
 
   //Create a struct to hold the device properties, we have to provide a buffer for the serial string
   LEAP_DEVICE_INFO deviceProperties = {
    
     sizeof(deviceProperties) };
   // Start with a length of 1 (pretending we don't know a priori what the length is).
   // Currently device serial numbers are all the same length, but that could change in the future
   deviceProperties.serial_length = 1;
   deviceProperties.serial = malloc(deviceProperties.serial_length);
   //This will fail since the serial buffer is only 1 character long
   // But deviceProperties is updated to contain the required buffer length
   result = LeapGetDeviceInfo(deviceHandle, &deviceProperties);
   if(result == eLeapRS_InsufficientBuffer){
    
    
     //try again with correct buffer size
     deviceProperties.serial = realloc(deviceProperties.serial, deviceProperties.serial_length);
     result = LeapGetDeviceInfo(deviceHandle, &deviceProperties);
     if(result != eLeapRS_Success){
    
    
       printf("Failed to get device info %s.\n", ResultString(result));
       free(deviceProperties.serial);
       return;
     }
   }
   setDevice(&deviceProperties);
   if(ConnectionCallbacks.on_device_found){
    
    
     ConnectionCallbacks.on_device_found(&deviceProperties);
   }
 
   free(deviceProperties.serial);
   LeapCloseDevice(deviceHandle);
 }
 
 /** Called by serviceMessageLoop() when a device lost event is returned by LeapPollConnection(). */
 static void handleDeviceLostEvent(const LEAP_DEVICE_EVENT *device_event){
    
    
   if(ConnectionCallbacks.on_device_lost){
    
    
     ConnectionCallbacks.on_device_lost();
   }
 }
 
 /** Called by serviceMessageLoop() when a device failure event is returned by LeapPollConnection(). */
 static void handleDeviceFailureEvent(const LEAP_DEVICE_FAILURE_EVENT *device_failure_event){
    
    
   if(ConnectionCallbacks.on_device_failure){
    
    
     ConnectionCallbacks.on_device_failure(device_failure_event->status, device_failure_event->hDevice);
   }
 }
 
 /** Called by serviceMessageLoop() when a tracking event is returned by LeapPollConnection(). */
 static void handleTrackingEvent(const LEAP_TRACKING_EVENT *tracking_event){
    
    
   setFrame(tracking_event); //support polling tracking data from different thread
   if(ConnectionCallbacks.on_frame){
    
    
     ConnectionCallbacks.on_frame(tracking_event);
   }
 }
 
 /** Called by serviceMessageLoop() when a log event is returned by LeapPollConnection(). */
 static void handleLogEvent(const LEAP_LOG_EVENT *log_event){
    
    
   if(ConnectionCallbacks.on_log_message){
    
    
     ConnectionCallbacks.on_log_message(log_event->severity, log_event->timestamp, log_event->message);
   }
 }
 
 /** Called by serviceMessageLoop() when a log event is returned by LeapPollConnection(). */
 static void handleLogEvents(const LEAP_LOG_EVENTS *log_events){
    
    
   if(ConnectionCallbacks.on_log_message){
    
    
     for (int i = 0; i < (int)(log_events->nEvents); i++) {
    
    
       const LEAP_LOG_EVENT* log_event = &log_events->events[i];
       ConnectionCallbacks.on_log_message(log_event->severity, log_event->timestamp, log_event->message);
     }
   }
 }
 
 /** Called by serviceMessageLoop() when a policy event is returned by LeapPollConnection(). */
 static void handlePolicyEvent(const LEAP_POLICY_EVENT *policy_event){
    
    
   if(ConnectionCallbacks.on_policy){
    
    
     ConnectionCallbacks.on_policy(policy_event->current_policy);
   }
 }
 
 /** Called by serviceMessageLoop() when a config change event is returned by LeapPollConnection(). */
 static void handleConfigChangeEvent(const LEAP_CONFIG_CHANGE_EVENT *config_change_event){
    
    
   if(ConnectionCallbacks.on_config_change){
    
    
     ConnectionCallbacks.on_config_change(config_change_event->requestID, config_change_event->status);
   }
 }
 
 /** Called by serviceMessageLoop() when a config response event is returned by LeapPollConnection(). */
 static void handleConfigResponseEvent(const LEAP_CONFIG_RESPONSE_EVENT *config_response_event){
    
    
   if(ConnectionCallbacks.on_config_response){
    
    
     ConnectionCallbacks.on_config_response(config_response_event->requestID, config_response_event->value);
   }
 }
 
 /** Called by serviceMessageLoop() when a point mapping change event is returned by LeapPollConnection(). */
 static void handleImageEvent(const LEAP_IMAGE_EVENT *image_event) {
    
    
   if(ConnectionCallbacks.on_image){
    
    
     ConnectionCallbacks.on_image(image_event);
   }
 }
 
 /** Called by serviceMessageLoop() when a point mapping change event is returned by LeapPollConnection(). */
 static void handlePointMappingChangeEvent(const LEAP_POINT_MAPPING_CHANGE_EVENT *point_mapping_change_event) {
    
    
   if(ConnectionCallbacks.on_point_mapping_change){
    
    
     ConnectionCallbacks.on_point_mapping_change(point_mapping_change_event);
   }
 }
 
 /** Called by serviceMessageLoop() when a point mapping change event is returned by LeapPollConnection(). */
 static void handleHeadPoseEvent(const LEAP_HEAD_POSE_EVENT *head_pose_event) {
    
    
     if(ConnectionCallbacks.on_head_pose){
    
    
       ConnectionCallbacks.on_head_pose(head_pose_event);
     }
 }
 
 /**
  * Services the LeapC message pump by calling LeapPollConnection().
  * The average polling time is determined by the framerate of the Leap Motion service.
  */
 #if defined(_MSC_VER)
 static void serviceMessageLoop(void * unused){
    
    
 #else
 static void* serviceMessageLoop(void * unused){
    
    
 #endif
   eLeapRS result;
   LEAP_CONNECTION_MESSAGE msg;
   while(_isRunning){
    
    
     unsigned int timeout = 1000;
     result = LeapPollConnection(connectionHandle, timeout, &msg);
 
     if(result != eLeapRS_Success){
    
    
       printf("LeapC PollConnection call was %s.\n", ResultString(result));
       continue;
     }
 
     switch (msg.type){
    
    
       case eLeapEventType_Connection:
         handleConnectionEvent(msg.connection_event);
         break;
       case eLeapEventType_ConnectionLost:
         handleConnectionLostEvent(msg.connection_lost_event);
         break;
       case eLeapEventType_Device:
         handleDeviceEvent(msg.device_event);
         break;
       case eLeapEventType_DeviceLost:
         handleDeviceLostEvent(msg.device_event);
         break;
       case eLeapEventType_DeviceFailure:
         handleDeviceFailureEvent(msg.device_failure_event);
         break;
       case eLeapEventType_Tracking:
         handleTrackingEvent(msg.tracking_event);
         break;
       case eLeapEventType_ImageComplete:
         // Ignore
         break;
       case eLeapEventType_ImageRequestError:
         // Ignore
         break;
       case eLeapEventType_LogEvent:
         handleLogEvent(msg.log_event);
         break;
       case eLeapEventType_Policy:
         handlePolicyEvent(msg.policy_event);
         break;
       case eLeapEventType_ConfigChange:
         handleConfigChangeEvent(msg.config_change_event);
         break;
       case eLeapEventType_ConfigResponse:
         handleConfigResponseEvent(msg.config_response_event);
         break;
       case eLeapEventType_Image:
         handleImageEvent(msg.image_event);
         break;
       case eLeapEventType_PointMappingChange:
         handlePointMappingChangeEvent(msg.point_mapping_change_event);
         break;
       case eLeapEventType_LogEvents:
         handleLogEvents(msg.log_events);
         break;
       case eLeapEventType_HeadPose:
         handleHeadPoseEvent(msg.head_pose_event);
         break;
       default:
         //discard unknown message types
         printf("Unhandled message type %i.\n", msg.type);
     } //switch on msg.type
   }
 #if !defined(_MSC_VER)
   return NULL;
 #endif
 }
 
 /* Used in Polling Example: */
 
 /**
  * Caches the newest frame by copying the tracking event struct returned by
  * LeapC.
  */
 void setFrame(const LEAP_TRACKING_EVENT *frame){
    
    
   LockMutex(&dataLock);
   if(!lastFrame) lastFrame = malloc(sizeof(*frame));
   *lastFrame = *frame;
   UnlockMutex(&dataLock);
 }
 
 /** Returns a pointer to the cached tracking frame. */
 LEAP_TRACKING_EVENT* GetFrame(){
    
    
   LEAP_TRACKING_EVENT *currentFrame;
 
   LockMutex(&dataLock);
   currentFrame = lastFrame;
   UnlockMutex(&dataLock);
 
   return currentFrame;
 }
 
 /**
  * Caches the last device found by copying the device info struct returned by
  * LeapC.
  */
 static void setDevice(const LEAP_DEVICE_INFO *deviceProps){
    
    
   LockMutex(&dataLock);
   if(lastDevice){
    
    
     free(lastDevice->serial);
   } else {
    
    
     lastDevice = malloc(sizeof(*deviceProps));
   }
   *lastDevice = *deviceProps;
   lastDevice->serial = malloc(deviceProps->serial_length);
   memcpy(lastDevice->serial, deviceProps->serial, deviceProps->serial_length);
   UnlockMutex(&dataLock);
 }
 
 /** Returns a pointer to the cached device info. */
 LEAP_DEVICE_INFO* GetDeviceProperties(){
    
    
   LEAP_DEVICE_INFO *currentDevice;
   LockMutex(&dataLock);
   currentDevice = lastDevice;
   UnlockMutex(&dataLock);
   return currentDevice;
 }
 
 //End of polling example-specific code
 
 /** Translates eLeapRS result codes into a human-readable string. */
 const char* ResultString(eLeapRS r) {
    
    
   switch(r){
    
    
     case eLeapRS_Success:                  return "eLeapRS_Success";
     case eLeapRS_UnknownError:             return "eLeapRS_UnknownError";
     case eLeapRS_InvalidArgument:          return "eLeapRS_InvalidArgument";
     case eLeapRS_InsufficientResources:    return "eLeapRS_InsufficientResources";
     case eLeapRS_InsufficientBuffer:       return "eLeapRS_InsufficientBuffer";
     case eLeapRS_Timeout:                  return "eLeapRS_Timeout";
     case eLeapRS_NotConnected:             return "eLeapRS_NotConnected";
     case eLeapRS_HandshakeIncomplete:      return "eLeapRS_HandshakeIncomplete";
     case eLeapRS_BufferSizeOverflow:       return "eLeapRS_BufferSizeOverflow";
     case eLeapRS_ProtocolError:            return "eLeapRS_ProtocolError";
     case eLeapRS_InvalidClientID:          return "eLeapRS_InvalidClientID";
     case eLeapRS_UnexpectedClosed:         return "eLeapRS_UnexpectedClosed";
     case eLeapRS_UnknownImageFrameRequest: return "eLeapRS_UnknownImageFrameRequest";
     case eLeapRS_UnknownTrackingFrameID:   return "eLeapRS_UnknownTrackingFrameID";
     case eLeapRS_RoutineIsNotSeer:         return "eLeapRS_RoutineIsNotSeer";
     case eLeapRS_TimestampTooEarly:        return "eLeapRS_TimestampTooEarly";
     case eLeapRS_ConcurrentPoll:           return "eLeapRS_ConcurrentPoll";
     case eLeapRS_NotAvailable:             return "eLeapRS_NotAvailable";
     case eLeapRS_NotStreaming:             return "eLeapRS_NotStreaming";
     case eLeapRS_CannotOpenDevice:         return "eLeapRS_CannotOpenDevice";
     default:                               return "unknown result type.";
   }
 }
 /** Cross-platform sleep function */
 void millisleep(int milliseconds){
    
    
 #ifdef _WIN32
     Sleep(milliseconds);
 #else
     usleep(milliseconds*1000);
 #endif
   }
 //End-of-ExampleConnection.c

效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39006214/article/details/122179118
今日推荐