版本
menu_open
link
目标平台:

include/AK/Tools/Win32/AkPlatformFuncs.h

浏览该文件的文档。
00001 /*******************************************************************************
00002 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
00003 released in source code form as part of the SDK installer package.
00004 
00005 Commercial License Usage
00006 
00007 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
00008 may use this file in accordance with the end user license agreement provided 
00009 with the software or, alternatively, in accordance with the terms contained in a
00010 written agreement between you and Audiokinetic Inc.
00011 
00012 Apache License Usage
00013 
00014 Alternatively, this file may be used under the Apache License, Version 2.0 (the 
00015 "Apache License"); you may not use this file except in compliance with the 
00016 Apache License. You may obtain a copy of the Apache License at 
00017 http://www.apache.org/licenses/LICENSE-2.0.
00018 
00019 Unless required by applicable law or agreed to in writing, software distributed
00020 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
00021 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
00022 the specific language governing permissions and limitations under the License.
00023 
00024   Version: <VERSION>  Build: <BUILDNUMBER>
00025   Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
00026 *******************************************************************************/
00027 
00028 #ifndef _AK_PLATFORM_FUNCS_H_
00029 #define _AK_PLATFORM_FUNCS_H_
00030 
00031 #include "malloc.h"
00032 #include <AK/Tools/Common/AkAssert.h>
00033 #include <AK/SoundEngine/Common/AkTypes.h>
00034 #include <windows.h>
00035 //#define AK_ENABLE_PERF_RECORDING
00036 #if defined(AK_ENABLE_PERF_RECORDING)
00037 #include <stdio.h>
00038 #endif
00039 
00040 #if defined(_WIN64)
00041 // on 64 bit, removes warning C4985: 'ceil': attributes not present on previous declaration.
00042 // see http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=294649
00043 #include <math.h>
00044 #endif // _WIN64
00045 #include <intrin.h>
00046 
00047 //-----------------------------------------------------------------------------
00048 // Platform-specific thread properties definition.
00049 //-----------------------------------------------------------------------------
00050 struct AkThreadProperties
00051 {
00052     int                 nPriority;      ///< Thread priority
00053 #ifdef AK_WIN_UNIVERSAL_APP
00054     PROCESSOR_NUMBER    processorNumber;///< Ideal processor (passed to SetThreadIdealProcessorEx)
00055 #else
00056     AkUInt32            dwAffinityMask; ///< Affinity mask
00057 #endif
00058     AkUInt32            uStackSize;     ///< Thread stack size.
00059 };
00060 
00061 //-----------------------------------------------------------------------------
00062 // External variables.
00063 //-----------------------------------------------------------------------------
00064 // g_fFreqRatio is used by time helpers to return time values in milliseconds.
00065 // It is declared and updated by the sound engine.
00066 namespace AK
00067 {
00068     extern AkReal32 g_fFreqRatio;
00069 }
00070 
00071 //-----------------------------------------------------------------------------
00072 // Defines for Win32.
00073 //-----------------------------------------------------------------------------
00074 #define AK_DECLARE_THREAD_ROUTINE( FuncName )   DWORD WINAPI FuncName(LPVOID lpParameter)
00075 #define AK_THREAD_RETURN( _param_ )             return (_param_);
00076 #define AK_THREAD_ROUTINE_PARAMETER             lpParameter
00077 #define AK_GET_THREAD_ROUTINE_PARAMETER_PTR(type) reinterpret_cast<type*>( AK_THREAD_ROUTINE_PARAMETER )
00078 #define AK_RETURN_THREAD_OK                     0x00000000
00079 #define AK_RETURN_THREAD_ERROR                  0x00000001
00080 #if defined AK_CPU_X86_64
00081 #define AK_DEFAULT_STACK_SIZE                   (65536)
00082 #else
00083 #define AK_DEFAULT_STACK_SIZE                   (32768)
00084 #endif
00085 #define AK_THREAD_PRIORITY_NORMAL               THREAD_PRIORITY_NORMAL
00086 #define AK_THREAD_PRIORITY_ABOVE_NORMAL         THREAD_PRIORITY_ABOVE_NORMAL
00087 
00088 // NULL objects
00089 #define AK_NULL_THREAD                          NULL
00090 
00091 #define AK_INFINITE                             INFINITE
00092 
00093 #define AkMax(x1, x2)   (((x1) > (x2))? (x1): (x2))
00094 #define AkMin(x1, x2)   (((x1) < (x2))? (x1): (x2))
00095 #define AkClamp(x, min, max)  ((x) < (min)) ? (min) : (((x) > (max) ? (max) : (x)))
00096 
00097 namespace AKPLATFORM
00098 {
00099     // Simple automatic event API
00100     // ------------------------------------------------------------------
00101     
00102     /// Platform Independent Helper
00103     inline void AkClearEvent( AkEvent & out_event )
00104     {
00105         out_event = NULL;
00106     }
00107 
00108     /// Platform Independent Helper
00109     inline AKRESULT AkCreateEvent( AkEvent & out_event )
00110     {
00111 #ifdef AK_USE_UWP_API
00112         out_event = CreateEventEx(nullptr, nullptr, 0, STANDARD_RIGHTS_ALL|EVENT_MODIFY_STATE);
00113 #else
00114         out_event = ::CreateEvent( NULL,                    // No security attributes
00115                                     false,                  // Reset type: automatic
00116                                     false,                  // Initial signaled state: not signaled
00117                                     NULL                    // No name
00118                                    );
00119 #endif
00120         return ( out_event ) ? AK_Success : AK_Fail;
00121     }
00122 
00123     /// Platform Independent Helper
00124     inline void AkDestroyEvent( AkEvent & io_event )
00125     {
00126         if ( io_event )
00127             ::CloseHandle( io_event );
00128         io_event = NULL;
00129     }
00130 
00131     /// Platform Independent Helper
00132     inline void AkWaitForEvent( AkEvent & in_event )
00133     {
00134 #ifdef AK_USE_UWP_API
00135 #ifdef AK_ENABLE_ASSERTS
00136         DWORD dwWaitResult = 
00137 #endif // AK_ENABLE_ASSERTS
00138             ::WaitForSingleObjectEx( in_event, INFINITE, FALSE );
00139         AKASSERT( dwWaitResult == WAIT_OBJECT_0 );
00140 #else
00141         AKVERIFY( ::WaitForSingleObject( in_event, INFINITE ) == WAIT_OBJECT_0 );
00142 #endif
00143     }
00144 
00145     /// Platform Independent Helper
00146     inline void AkSignalEvent( const AkEvent & in_event )
00147     {
00148         AKVERIFY( ::SetEvent( in_event ) );
00149     }
00150 
00151     
00152     // Atomic Operations
00153     // ------------------------------------------------------------------
00154 
00155     /// Platform Independent Helper
00156     inline AkInt32 AkInterlockedIncrement(AkAtomic32 * pValue)
00157     {
00158         return InterlockedIncrement( pValue );
00159     }
00160 
00161     /// Platform Independent Helper
00162     inline AkInt32 AkInterlockedDecrement(AkAtomic32 * pValue)
00163     {
00164         return InterlockedDecrement( pValue );
00165     }
00166 
00167 #ifdef AK_CPU_X86_64
00168     inline bool AkInterlockedCompareExchange( volatile AkAtomic64* io_pDest, AkInt64 in_newValue, AkInt64 in_expectedOldVal )
00169     {
00170         return _InterlockedCompareExchange64(io_pDest, in_newValue, in_expectedOldVal) == in_expectedOldVal;
00171     }
00172 #endif
00173 
00174     inline bool AkInterlockedCompareExchange(volatile AkAtomic32* io_pDest, AkInt32 in_newValue, AkInt32 in_expectedOldVal)
00175     {
00176         return InterlockedCompareExchange(io_pDest, in_newValue, in_expectedOldVal) == in_expectedOldVal;
00177     }
00178 
00179 #if defined AK_CPU_X86 || defined AK_CPU_ARM
00180     inline bool AkInterlockedCompareExchange(volatile AkAtomicPtr* io_pDest, AkIntPtr in_newValue, AkIntPtr in_expectedOldVal)
00181     {
00182         return InterlockedCompareExchange((volatile LONG_PTR*)io_pDest, (LONG_PTR)in_newValue, (LONG_PTR)in_expectedOldVal) == in_expectedOldVal;
00183     }
00184 #endif      
00185 
00186     //Ensure that all write operations are complete.  Necessary only on platforms that don't garentee the order of writes.
00187     inline void AkMemoryBarrier() 
00188     {
00189         _ReadWriteBarrier();
00190     }
00191 
00192     // Threads
00193     // ------------------------------------------------------------------
00194 
00195     /// Platform Independent Helper
00196     inline bool AkIsValidThread( AkThread * in_pThread )
00197     {
00198         return (*in_pThread != AK_NULL_THREAD);
00199     }
00200 
00201     /// Platform Independent Helper
00202     inline void AkClearThread( AkThread * in_pThread )
00203     {
00204         *in_pThread = AK_NULL_THREAD;
00205     }
00206 
00207     /// Platform Independent Helper
00208     inline void AkCloseThread( AkThread * in_pThread )
00209     {
00210         AKASSERT( in_pThread );
00211         AKASSERT( *in_pThread );
00212         AKVERIFY( ::CloseHandle( *in_pThread ) );
00213         AkClearThread( in_pThread );
00214     }
00215 
00216 #define AkExitThread( _result ) return _result;
00217 
00218     /// Platform Independent Helper
00219     inline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
00220     {
00221         out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
00222         out_threadProperties.uStackSize= AK_DEFAULT_STACK_SIZE;
00223 #ifdef AK_WIN_UNIVERSAL_APP
00224         out_threadProperties.processorNumber.Group = 0;
00225         out_threadProperties.processorNumber.Number = MAXIMUM_PROCESSORS;
00226         out_threadProperties.processorNumber.Reserved = 0;
00227 #else
00228         out_threadProperties.dwAffinityMask = 0;
00229 #endif
00230     }
00231 
00232     /// Set the name of a thread: see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
00233     inline void AkSetThreadName( DWORD in_dwThreadID, LPCSTR in_szThreadName )
00234     {
00235         const DWORD MS_VC_EXCEPTION=0x406D1388;
00236 
00237 #pragma pack(push,8)
00238         typedef struct tagTHREADNAME_INFO
00239         {
00240             DWORD dwType;
00241             LPCSTR szName;
00242             DWORD dwThreadID;
00243             DWORD dwFlags;
00244         } THREADNAME_INFO;
00245 #pragma pack(pop)
00246 
00247         THREADNAME_INFO info;
00248         info.dwType = 0x1000;
00249         info.szName = in_szThreadName;
00250         info.dwThreadID = in_dwThreadID;
00251         info.dwFlags = 0;
00252 
00253         __try
00254         {
00255             RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
00256         }
00257 #pragma warning(suppress: 6312 6322)
00258         __except(EXCEPTION_CONTINUE_EXECUTION)
00259         {
00260         }
00261     }
00262 
00263     /// Platform Independent Helper
00264     inline void AkCreateThread( 
00265         AkThreadRoutine pStartRoutine,                  // Thread routine.
00266         void * pParams,                                 // Routine params.
00267         const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
00268         AkThread * out_pThread,                         // Returned thread handle.
00269         const char * in_szThreadName )                      // Opt thread name.
00270     {
00271         AKASSERT( out_pThread != NULL );
00272         AKASSERT( (in_threadProperties.nPriority >= THREAD_PRIORITY_LOWEST && in_threadProperties.nPriority <= THREAD_PRIORITY_HIGHEST)
00273             || ( in_threadProperties.nPriority == THREAD_PRIORITY_TIME_CRITICAL ) );
00274 
00275         DWORD dwThreadID;
00276         *out_pThread = ::CreateThread( NULL,                            // No security attributes
00277                                        in_threadProperties.uStackSize,  // StackSize (0 uses system default)
00278                                        pStartRoutine,                   // Thread start routine
00279                                        pParams,                         // Thread function parameter
00280                                        0,                               // Creation flags: create running
00281                                        &dwThreadID );
00282 
00283         // ::CreateThread() return NULL if it fails.
00284         if ( !*out_pThread )
00285         {
00286             AkClearThread( out_pThread );
00287             return;
00288         }
00289 
00290         // Set thread name.
00291         AkSetThreadName( dwThreadID, in_szThreadName );
00292 
00293         // Set properties.
00294         if ( !::SetThreadPriority( *out_pThread, in_threadProperties.nPriority ) )
00295         {
00296             AKASSERT( !"Failed setting thread priority" );
00297             AkCloseThread( out_pThread );
00298             return;
00299         }
00300 #ifdef AK_WIN_UNIVERSAL_APP
00301         if ( in_threadProperties.processorNumber.Number != MAXIMUM_PROCESSORS)
00302         {
00303             if ( !SetThreadIdealProcessorEx( *out_pThread, const_cast<PPROCESSOR_NUMBER>(&in_threadProperties.processorNumber), NULL) )
00304             {
00305                 AKASSERT( !"Failed setting thread ideal processor" );
00306                 AkCloseThread( out_pThread );
00307             }
00308         }
00309 #else
00310         if (in_threadProperties.dwAffinityMask)
00311         {
00312             if (!::SetThreadAffinityMask(*out_pThread, in_threadProperties.dwAffinityMask))
00313             {
00314                 AKASSERT(!"Failed setting thread affinity mask");
00315                 AkCloseThread(out_pThread);
00316             }
00317         }
00318 #endif
00319     }
00320 
00321     /// Platform Independent Helper
00322     inline void AkWaitForSingleThread( AkThread * in_pThread )
00323     {
00324         AKASSERT( in_pThread );
00325         AKASSERT( *in_pThread );
00326 #ifdef AK_USE_UWP_API
00327         ::WaitForSingleObjectEx( *in_pThread, INFINITE, FALSE );
00328 #else
00329         ::WaitForSingleObject( *in_pThread, INFINITE );
00330 #endif
00331     }
00332 
00333     /// Returns the calling thread's ID.
00334     inline AkThreadID CurrentThread()
00335     {
00336         return ::GetCurrentThreadId();
00337     }
00338 
00339     /// Platform Independent Helper
00340     inline void AkSleep( AkUInt32 in_ulMilliseconds )
00341     {
00342         ::Sleep( in_ulMilliseconds );
00343     }
00344 
00345     // Optimized memory functions
00346     // --------------------------------------------------------------------
00347 
00348     /// Platform Independent Helper
00349     inline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
00350     {
00351         memcpy( pDest, pSrc, uSize );
00352     }
00353 
00354     /// Platform Independent Helper
00355     inline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
00356     {
00357         memset( pDest, iVal, uSize );
00358     }
00359 
00360     // Time functions
00361     // ------------------------------------------------------------------
00362 
00363     /// Platform Independent Helper
00364     inline void PerformanceCounter( AkInt64 * out_piLastTime )
00365     {
00366         ::QueryPerformanceCounter( (LARGE_INTEGER*)out_piLastTime );
00367     }
00368 
00369     /// Platform Independent Helper
00370     inline void PerformanceFrequency( AkInt64 * out_piFreq )
00371     {
00372         ::QueryPerformanceFrequency( (LARGE_INTEGER*)out_piFreq );
00373     }
00374 
00375     /// Platform Independent Helper
00376     inline void UpdatePerformanceFrequency()
00377     {
00378         AkInt64 iFreq;
00379         PerformanceFrequency( &iFreq );
00380         AK::g_fFreqRatio = (AkReal32)( iFreq / 1000 );
00381     }
00382 
00383     /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
00384     inline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
00385     {
00386         return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
00387     }
00388 
00389     /// String conversion helper
00390     inline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
00391                                      AkUInt32   in_uiOutBufferSize,
00392                                      char*  io_pszAnsiString )
00393     {
00394         int iWritten = ::WideCharToMultiByte(CP_ACP,                                                                    // code page
00395                                     0,                                                                      // performance and mapping flags
00396                                     in_pszUnicodeString,                                                    // wide-character string
00397                                     (int)AkMin( ( (AkUInt32)wcslen( in_pszUnicodeString )), in_uiOutBufferSize-1 ), // number of chars in string : -1 = NULL terminated string.
00398                                     io_pszAnsiString,                                                       // buffer for new string
00399                                     in_uiOutBufferSize,                                                     // size of buffer
00400                                     NULL,                                                                   // default for unmappable chars
00401                                     NULL);                                                                  // set when default char used
00402         io_pszAnsiString[iWritten] = 0;
00403         return iWritten;
00404     }
00405 
00406     /// String conversion helper
00407     inline AkInt32 AkCharToWideChar( const char*    in_pszAnsiString,
00408                                      AkUInt32       in_uiOutBufferSize,
00409                                      void*          io_pvUnicodeStringBuffer )
00410     {
00411         return ::MultiByteToWideChar(   CP_ACP,                             // code page
00412                                         0,                                  // performance and mapping flags
00413                                         in_pszAnsiString,                   // wide-character string
00414                                         -1,                                 // number of chars in string : -1 = NULL terminated string.
00415                                         (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
00416                                         in_uiOutBufferSize);                // size of buffer
00417     }
00418 
00419     /// String conversion helper
00420     inline AkInt32 AkUtf8ToWideChar( const char*    in_pszUtf8String,
00421                                      AkUInt32       in_uiOutBufferSize,
00422                                      void*          io_pvUnicodeStringBuffer )
00423     {
00424         return ::MultiByteToWideChar(   CP_UTF8,                            // code page
00425                                         0,                                  // performance and mapping flags
00426                                         in_pszUtf8String,                   // wide-character string
00427                                         -1,                                 // number of chars in string : -1 = NULL terminated string.
00428                                         (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
00429                                         in_uiOutBufferSize);                // size of buffer
00430     }
00431 
00432     /// Safe unicode string copy.
00433     inline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
00434     {
00435         size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
00436         wcsncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
00437         in_pDest[iSizeCopy] = '\0';
00438     }
00439 
00440     /// Safe string copy.
00441     inline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
00442     {
00443         size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
00444         strncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
00445         in_pDest[iSizeCopy] = '\0';
00446     }
00447 
00448     /// Safe unicode string concatenation.
00449     inline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
00450     {
00451         int iAvailableSize = (int)( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
00452         wcsncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)wcslen( in_pSrc ) ) );
00453     }
00454 
00455     /// Safe string concatenation.
00456     inline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
00457     {
00458         int iAvailableSize = (int)( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
00459         strncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)strlen( in_pSrc ) ) );
00460     }
00461 
00462     /// Stack allocations.
00463     #define AkAlloca( _size_ ) _alloca( _size_ )
00464 
00465     /// Output a debug message on the console
00466 #if ! ( defined(AK_USE_UWP_API) || defined(AK_OPTIMIZED) )
00467     inline void OutputDebugMsg( const wchar_t* in_pszMsg )
00468     {
00469         OutputDebugStringW( in_pszMsg );
00470     }
00471 
00472     /// Output a debug message on the console
00473     inline void OutputDebugMsg( const char* in_pszMsg )
00474     {
00475         OutputDebugStringA( in_pszMsg );
00476     }
00477 #else
00478     inline void OutputDebugMsg( const wchar_t* ){}
00479     inline void OutputDebugMsg( const char* ){}
00480 #endif
00481 
00482     /// Converts a wchar_t string to an AkOSChar string.
00483     /// \remark On some platforms the AkOSChar string simply points to the same string,
00484     /// on others a new buffer is allocated on the stack using AkAlloca. This means
00485     /// you must make sure that:
00486     /// - The source string stays valid and unmodified for as long as you need the
00487     ///   AkOSChar string (for cases where they point to the same string)
00488     /// - The AkOSChar string is used within this scope only -- for example, do NOT
00489     ///   return that string from a function (for cases where it is allocated on the stack)
00490     #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _wstring_ )
00491 
00492     /// Converts a char string to an AkOSChar string.
00493     /// \remark On some platforms the AkOSChar string simply points to the same string,
00494     /// on others a new buffer is allocated on the stack using AkAlloca. This means
00495     /// you must make sure that:
00496     /// - The source string stays valid and unmodified for as long as you need the
00497     ///   AkOSChar string (for cases where they point to the same string)
00498     /// - The AkOSChar string is used within this scope only -- for example, do NOT
00499     ///   return that string from a function (for cases where it is allocated on the stack)
00500     #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) \
00501            _oscharstring_ = (AkOSChar*)AkAlloca( (1 + strlen( _astring_ )) * sizeof(AkOSChar)); \
00502            AKPLATFORM::AkCharToWideChar( _astring_, (AkUInt32)(1 + strlen(_astring_ )), (AkOSChar*)( _oscharstring_ ) )
00503 
00504     /// Converts a AkOSChar string into wide char string.
00505     /// \remark On some platforms the AkOSChar string simply points to the same string,
00506     /// on others a new buffer is allocated on the stack using AkAlloca. This means
00507     /// you must make sure that:
00508     /// - The source string stays valid and unmodified for as long as you need the
00509     ///   AkOSChar string (for cases where they point to the same string)
00510     /// - The AkOSChar string is used within this scope only -- for example, do NOT
00511     ///   return that string from a function (for cases where it is allocated on the stack)
00512     #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) _wstring_ = _osstring_
00513 
00514     /// Converts a AkOSChar string into char string.
00515     /// \remark On some platforms the AkOSChar string simply points to the same string,
00516     /// on others a new buffer is allocated on the stack using AkAlloca. This means
00517     /// you must make sure that:
00518     /// - The source string stays valid and unmodified for as long as you need the
00519     ///   AkOSChar string (for cases where they point to the same string)
00520     /// - The AkOSChar string is used within this scope only -- for example, do NOT
00521     ///   return that string from a function (for cases where it is allocated on the stack)
00522     #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) \
00523             _astring_ = (char*)AkAlloca( 1 + wcslen( _osstring_ )); \
00524             AKPLATFORM::AkWideCharToChar( _osstring_, AkUInt32(1 + wcslen( _osstring_ )), _astring_ );
00525 
00526     /// Get the length, in characters, of a NULL-terminated AkUtf16 string
00527     /// \return The length, in characters, of the specified string (excluding terminating NULL)
00528     inline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
00529     {
00530         return ( wcslen( in_pStr ) );
00531     }
00532 
00533     /// Get the length, in characters, of a NULL-terminated AkOSChar string
00534     /// \return The length, in characters, of the specified string (excluding terminating NULL)
00535     inline size_t OsStrLen( const AkOSChar* in_pszString )
00536     {
00537         return ( wcslen( in_pszString ) );
00538     }
00539 
00540     /// AkOSChar version of sprintf().
00541     #define AK_OSPRINTF swprintf_s
00542 
00543     /// Compare two NULL-terminated AkOSChar strings
00544     /// \return
00545     /// - < 0 if in_pszString1 < in_pszString2
00546     /// -    0 if the two strings are identical
00547     /// - > 0 if in_pszString1 > in_pszString2
00548     /// \remark The comparison is case-sensitive
00549     inline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
00550     {
00551         return ( wcscmp( in_pszString1,  in_pszString2 ) );
00552     }
00553     
00554     #define AK_UTF16_TO_WCHAR(  in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00555     #define AK_WCHAR_TO_UTF16(  in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00556     #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00557     #define AK_UTF16_TO_CHAR(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
00558     #define AK_CHAR_TO_UTF16(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
00559     #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00560 
00561     // Use with AkOSChar.
00562     #define AK_PATH_SEPARATOR   (L"\\")
00563 
00564     #if defined(AK_ENABLE_PERF_RECORDING)
00565     
00566         static AkUInt32 g_uAkPerfRecExecCount = 0;  
00567         static AkReal32 g_fAkPerfRecExecTime = 0.f;
00568 
00569         #define AK_PERF_RECORDING_RESET()   \
00570             AKPLATFORM::g_uAkPerfRecExecCount = 0;\
00571             AKPLATFORM::g_fAkPerfRecExecTime = 0.f;
00572 
00573         #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )                       \
00574             AkInt64 iAkPerfRecTimeBefore;                                                                                           \
00575             if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) )    \
00576                 AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeBefore );
00577 
00578         #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )                        \
00579         if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) )    \
00580             {                                                                                                                       \
00581                 AkInt64 iAkPerfRecTimeAfter;                                                                                        \
00582                 AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeAfter );                                                             \
00583                 AKPLATFORM::g_fAkPerfRecExecTime += AKPLATFORM::Elapsed( iAkPerfRecTimeAfter, iAkPerfRecTimeBefore );                           \
00584                 if ( AKPLATFORM::g_uAkPerfRecExecCount == (__uExecutionCountStop__) )                                                           \
00585                 {                                                                                                                   \
00586                     AkReal32 fAverageExecutionTime = AKPLATFORM::g_fAkPerfRecExecTime/((__uExecutionCountStop__)-(__uExecutionCountStart__));   \
00587                     char str[256];                                                                                                  \
00588                     sprintf_s(str, 256, "%s average execution time: %f\n", __StorageName__, fAverageExecutionTime);                 \
00589                     AKPLATFORM::OutputDebugMsg( str );                                                                              \
00590                 }                                                                                                                   \
00591             }                                                                                                                       \
00592             AKPLATFORM::g_uAkPerfRecExecCount++;
00593     #endif // AK_ENABLE_PERF_RECORDING
00594 }
00595 
00596 #ifdef AK_ENABLE_INSTRUMENT
00597     #ifdef AK_XBOXONE
00598         #include <AK/Tools/XBoxOne/AkInstrument.h>
00599     #endif
00600 #endif
00601 
00602 #endif  // _AK_PLATFORM_FUNCS_H_

此页面对您是否有帮助?

需要技术支持?

仍有疑问?或者问题?需要更多信息?欢迎联系我们,我们可以提供帮助!

查看我们的“技术支持”页面

介绍一下自己的项目。我们会竭力为您提供帮助。

来注册自己的项目,我们帮您快速入门,不带任何附加条件!

开始 Wwise 之旅