using DeepSpeechClient.Structs; using System; using System.Runtime.InteropServices; using System.Text; namespace DeepSpeechClient.Extensions { internal static class NativeExtensions { /// /// Converts native pointer to UTF-8 encoded string. /// /// Native pointer. /// Optional parameter to release the native pointer. /// Result string. internal static string PtrToString(this IntPtr intPtr, bool releasePtr = true) { int len = 0; while (Marshal.ReadByte(intPtr, len) != 0) ++len; byte[] buffer = new byte[len]; Marshal.Copy(intPtr, buffer, 0, buffer.Length); if (releasePtr) NativeImp.DS_FreeString(intPtr); string result = Encoding.UTF8.GetString(buffer); return result; } /// /// Converts a pointer into managed TokenMetadata object. /// /// Native pointer. /// TokenMetadata managed object. private static Models.TokenMetadata PtrToTokenMetadata(this IntPtr intPtr) { var token = Marshal.PtrToStructure(intPtr); var managedToken = new Models.TokenMetadata { Timestep = token.timestep, StartTime = token.start_time, Text = token.text.PtrToString(releasePtr: false) }; return managedToken; } /// /// Converts a pointer into managed CandidateTranscript object. /// /// Native pointer. /// CandidateTranscript managed object. private static Models.CandidateTranscript PtrToCandidateTranscript(this IntPtr intPtr) { var managedTranscript = new Models.CandidateTranscript(); var transcript = Marshal.PtrToStructure(intPtr); managedTranscript.Tokens = new Models.TokenMetadata[transcript.num_tokens]; managedTranscript.Confidence = transcript.confidence; //we need to manually read each item from the native ptr using its size var sizeOfTokenMetadata = Marshal.SizeOf(typeof(TokenMetadata)); for (int i = 0; i < transcript.num_tokens; i++) { managedTranscript.Tokens[i] = transcript.tokens.PtrToTokenMetadata(); transcript.tokens += sizeOfTokenMetadata; } return managedTranscript; } /// /// Converts a pointer into managed Metadata object. /// /// Native pointer. /// Metadata managed object. internal static Models.Metadata PtrToMetadata(this IntPtr intPtr) { var managedMetadata = new Models.Metadata(); var metadata = Marshal.PtrToStructure(intPtr); managedMetadata.Transcripts = new Models.CandidateTranscript[metadata.num_transcripts]; //we need to manually read each item from the native ptr using its size var sizeOfCandidateTranscript = Marshal.SizeOf(typeof(CandidateTranscript)); for (int i = 0; i < metadata.num_transcripts; i++) { managedMetadata.Transcripts[i] = metadata.transcripts.PtrToCandidateTranscript(); metadata.transcripts += sizeOfCandidateTranscript; } NativeImp.DS_FreeMetadata(intPtr); return managedMetadata; } } }