protected void ProcessFrame(int width, int height, int pitch, PixelFormat format, IntPtr pBits) { if (format == PixelFormat.Undefined) { DebugMessage("Unsupported render target format"); return; } if (pBits == IntPtr.Zero) { DebugMessage("No image data"); return; } // Copy the image data from the buffer int size = height * pitch; var data = new byte[size]; try { try { Marshal.Copy(pBits, data, 0, size); producer.Write(intPtr => { MetaDataStruct metaData = new MetaDataStruct(data.Length, width, height, pitch, format); FastStructure.StructureToPtr(ref metaData, intPtr); intPtr += FastStructure <MetaDataStruct> .Size; FastStructure.WriteArray <byte>(intPtr, data, 0, data.Length); return(0); }, 0); // skip frame if we cannot write to circular buffer immediately } catch (TimeoutException) { // If we could not acquire write lock skip frame } catch (AccessViolationException) { // In this specifc case we are ignoring CSE (corrupted state exception) // It could happen during Window resizing. // If someone knows are better way please feel free to contribute // Because there is a timout in the resizing hook this exception should never be thrown } } catch (ObjectDisposedException) { // swallow exception to not crash hooked process } }
public void CanAllocHGlobalReadWrite() { IntPtr mem = Marshal.AllocHGlobal(FastStructure.SizeOf <ComplexStructure>()); ComplexStructure n = new ComplexStructure(); n.Compatible.Integer1 = 1; n.Compatible.Bookend = 2; n.FirstElement = 3; n.FinalElement = 9; unsafe { n.Compatible.Contents[0] = 4; n.Compatible.Contents[7] = 5; } FastStructure.StructureToPtr(ref n, mem); // Assert that the reading and writing result in same structure ComplexStructure m = FastStructure.PtrToStructure <ComplexStructure>(mem); Assert.Equal(n, m); Assert.Equal(n.Compatible.Integer1, m.Compatible.Integer1); Assert.Equal(n.Compatible.Bookend, m.Compatible.Bookend); unsafe { Assert.Equal(n.Compatible.Contents[0], m.Compatible.Contents[0]); Assert.Equal(n.Compatible.Contents[7], m.Compatible.Contents[7]); } // Assert that Marshal.PtrToStructure is compatible m = (ComplexStructure)Marshal.PtrToStructure(mem, typeof(ComplexStructure)); Assert.Equal(n, m); Assert.Equal(n.Compatible.Integer1, m.Compatible.Integer1); Assert.Equal(n.Compatible.Bookend, m.Compatible.Bookend); unsafe { Assert.Equal(n.Compatible.Contents[0], m.Compatible.Contents[0]); Assert.Equal(n.Compatible.Contents[7], m.Compatible.Contents[7]); } Marshal.FreeHGlobal(mem); }
/// <summary> /// Write <paramref name="message"/> into the next available /// node's buffer at <paramref name="ptr"/>. /// </summary> /// <param name="message"></param> /// <param name="ptr"></param> /// <returns></returns> private int WriteMessage(InteropMessage message, IntPtr ptr) { int bytesWritten = 0; // Write the target name (varying length string) byte[] target = Encoding.UTF8.GetBytes(message.target); int targetLen = target.Length; FastStructure.StructureToPtr(ref targetLen, ptr + bytesWritten); bytesWritten += FastStructure.SizeOf <int>(); if (targetLen > 0) { FastStructure.WriteBytes(ptr + bytesWritten, target, 0, targetLen); bytesWritten += targetLen; } // Write the message header var headerSize = FastStructure.SizeOf <InteropMessageHeader>(); var header = message.header; FastStructure.StructureToPtr(ref header, ptr + bytesWritten); bytesWritten += headerSize; // If there's a custom producer, execute it for writing the payload if (message.producer != null) { bytesWritten += message.producer(message.target, header, ptr + bytesWritten); } // If there's a payload included with the message, copy it if (message.payload != null) { FastStructure.WriteBytes(ptr + bytesWritten, message.payload, 0, message.payload.Length); bytesWritten += message.payload.Length; } // InteropLogger.Debug($"Produce {bytesWritten} bytes - {header.type} for `{message.target}`"); return(bytesWritten); }
internal static unsafe void StructureToPtr <T>(ref T structure, byte *ptr) where T : struct { FastStructure.StructureToPtr <T>(ref structure, (IntPtr)ptr); }