Created
July 22, 2018 15:30
-
-
Save Nihlus/761568243383b9cfe82cbac676574a8b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
using AdvancedDLSupport; | |
namespace Scratchpad | |
{ | |
public struct BsDiffStream_Impl | |
{ | |
public readonly IntPtr userData; | |
public readonly IntPtr malloc; | |
public readonly IntPtr free; | |
public readonly IntPtr write; | |
public delegate IntPtr malloc_impl(UIntPtr size); | |
public delegate void free_impl(IntPtr memPtr); | |
public delegate int write_impl(IntPtr currentApi, IntPtr buffer, int size); | |
public BsDiffStream_Impl(IntPtr userData, IntPtr malloc, IntPtr free, IntPtr write) | |
{ | |
this.userData = userData; | |
this.malloc = malloc; | |
this.free = free; | |
this.write = write; | |
} | |
} | |
public struct BsDiffStream | |
{ | |
public readonly IntPtr UserData; | |
public readonly Func<UIntPtr, IntPtr> AllocateMemory; | |
public readonly Action<IntPtr> FreeMemory; | |
public readonly Func<BsDiffStream, IntPtr, int, int> WriteData; | |
public BsDiffStream(IntPtr userData, Func<UIntPtr, IntPtr> allocateMemory, Action<IntPtr> freeMemory, Func<BsDiffStream, IntPtr, int, int> writeData) | |
{ | |
this.UserData = userData; | |
this.AllocateMemory = allocateMemory; | |
this.FreeMemory = freeMemory; | |
this.WriteData = writeData; | |
} | |
} | |
public static class Program | |
{ | |
private static Dictionary<IntPtr, FileStream> openStreams = new Dictionary<IntPtr, FileStream>(); | |
static void Main(string[] args) | |
{ | |
var fs = File.Open("native_written.txt", FileMode.Create); | |
openStreams.Add((IntPtr)1, fs); | |
var api = new BsDiffStream | |
( | |
(IntPtr)1, | |
size => Marshal.AllocHGlobal((int)size), | |
Marshal.FreeHGlobal, | |
NativeWrite | |
); | |
var apiImpl = new BsDiffStream_Impl | |
( | |
api.UserData, | |
Marshal.GetFunctionPointerForDelegate(new BsDiffStream_Impl.malloc_impl(api.AllocateMemory)), | |
Marshal.GetFunctionPointerForDelegate(new BsDiffStream_Impl.free_impl(api.FreeMemory)), | |
Marshal.GetFunctionPointerForDelegate(new BsDiffStream_Impl.write_impl((apiPtr, buffer, size) => NativeWrite_Impl_Wrapper(apiPtr, buffer, size, api.WriteData))) | |
); | |
// Mock native call | |
unsafe | |
{ | |
void* apiPtr = &apiImpl; | |
var textPtr = stackalloc byte[4]; | |
textPtr[0] = 84; | |
textPtr[1] = 69; | |
textPtr[2] = 83; | |
textPtr[3] = 84; | |
var callable = Marshal.GetDelegateForFunctionPointer<BsDiffStream_Impl.write_impl>(apiImpl.write); | |
callable(new IntPtr(apiPtr), new IntPtr(textPtr), 4); | |
} | |
fs.Dispose(); | |
} | |
private static int NativeWrite_Impl_Wrapper(IntPtr api, IntPtr buffer, int size, Func<BsDiffStream, IntPtr, int, int> actual) | |
{ | |
var apiObj = Marshal.PtrToStructure<BsDiffStream_Impl>(api); | |
var currentApi = new BsDiffStream(apiObj.userData, null, null, null); | |
return actual(currentApi, buffer, size); | |
} | |
private static int NativeWrite(BsDiffStream api, IntPtr buffer, int size) | |
{ | |
try | |
{ | |
unsafe | |
{ | |
var fs = openStreams[api.UserData]; | |
var bufferSpan = new Span<byte>(buffer.ToPointer(), size); | |
fs.Write(bufferSpan.ToArray(), 0, bufferSpan.Length); | |
fs.Flush(); | |
} | |
} | |
catch | |
{ | |
return -1; | |
} | |
return 0; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment