Skip to content

Instantly share code, notes, and snippets.

@Nihlus
Created July 22, 2018 15:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nihlus/761568243383b9cfe82cbac676574a8b to your computer and use it in GitHub Desktop.
Save Nihlus/761568243383b9cfe82cbac676574a8b to your computer and use it in GitHub Desktop.
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