Reputation: 2914
I'm using a native/unmanaged C++ DLL in my C# application. I call a native function to register a callback method in C# using PInvoke:
[DllImport("MyHook.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U1)] // necessary due to http://dotnet.dzone.com/articles/pinvoke-c-bool-return-values
private static extern bool InstallHook(CallbackPrototype callback);
private delegate int CallbackPrototype(byte* bytes, int size, int max);
// ...
var callback = new CallbackPrototype(MyCallback);
_callbackHandle = GCHandle.Alloc(callback);
var result = InstallHook(callback);
// somewhere when I'm removing the hook, I call _callbackHandle.Free();
Then, when an event happens, the native C++ DLL calls my callback.
private int MyCallback(byte* bytes, int size, int max)
{
//var buffer = new byte[size]; // A
//Marshal.Copy(new IntPtr(bytes), buffer, 0, size); // B
//WrapperInstance.ParseBytes(buffer, 0, size); // C
var x = 1 + 1; // D
return size;
}
When everything is commented out, it works well. If I start uncommenting line A in the callback, it gets veeery slow. I notice it because the callback is called in a critical moment. It isn't acceptable that the callback runtime duration is so long that I notice it as a human being.
How could this happen? The size parameter is only from one to 100. Thats only 100 bytes at maximum that need to be allocated - very few for todays computers. I need improvements to make the runtime of the callback much faster. Any ideas?
To go further in testing, I've added line D. This does not have any impact.
Edit: For more detailed testing I've allocated a big buffer when the class is created. So line A is not in the callback anymore. If line B is then commented out, it suddenly starts taking a huge amount of time again. This must have something to do with the managed code / virtual machine. I hope there are possibilities to make it faster.
Upvotes: 1
Views: 1196
Reputation: 3833
What you're basically doing is copying the bytes over into your buffer, and then parsing them afterwards. You could do that in one go, like so:
var bytes = ReadBytes(address, Marshal.SizeOf(typeof(T)), isRelative);
fixed (byte* b = bytes)
return (T) Marshal.PtrToStructure(new IntPtr(b), typeof (T));
I've taken this example from my memory library, and I reckon it'll be quite a bit faster than the code you're using right now, assuming you're attempting to retrieve value types only.
Upvotes: 2