3

I am currently browsing decompiled C# IL (with ILSpy) to get an impression on how some of the methods from System.Runtime.InteropServices are (could be) implemented. When I wanted to check how Marshal.Copy() is implemented, I found out that it only calls CopyToNative(), which is defined as follows:

// System.Runtime.InteropServices.Marshal
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void CopyToNative(object source, int startIndex, IntPtr destination, int length);

Where is it implemented? Is there any chance to look at its (decompiled) source code? If not, does anyone have a clue on how it could be implemented?

Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116
user1622959
  • 227
  • 3
  • 12

1 Answers1

6

The MethodImplAttribute and extern keyword indicate that this function is internal to the .NET runtime itself. This function is almost certainly implemented in C or C++ in the runtime's source code.

Without access to the runtime's source code your only real option is to disassemble this particular function and examine the assembly. (Please note that doing this may violate the EULA of your runtime.)


You might consider looking at Mono's source code to get a look at one possible implementation.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Thanks for all the info. If `CopyToNative()` is implemented in C/C++, shouldn't I then find a `PInvoke` definition somewhere? – user1622959 Jan 25 '13 at 17:24
  • 1
    @user1622959 `InternalCall` is similar to PInvoke, but not the same. It means that the framework *somehow* takes care of implementing that method, it's not just an import of C function from some DLL like PInvoke. – svick Jan 25 '13 at 17:47
  • 1
    Also, you might want to look at [Shared Source Common Language Infrastructure](http://en.wikipedia.org/wiki/Shared_Source_Common_Language_Infrastructure) as an alternative to mono. – svick Jan 25 '13 at 17:51
  • @user1622959 svick is right; `MethodImplOptions.InternalCall` usually means "this function/method is implemented in unmanaged code within the runtime itself." The only real difference between this and a P/Invoke call is that the runtime doesn't look for the named symbol in an external library with `InternalCall`. – cdhowie Jan 25 '13 at 18:52
  • If you do look at the SSCLI code, note that this will prevent you from contributing to alternative implementations of the .NET framework. If you might want to contribute a patch to Mono in the future, do not look at the SSCLI source code. – cdhowie Jan 25 '13 at 18:54
  • I did some benchmarking for `Marshal.Copy()` (.NET) and a simple own implementation that basically only calls `RtlCopyMemory` via `PInvoke` for small data sizes (here: 10-element `int` array copied a few thousand times back and forth between an array and native storage). `Marshal.Copy` was over two times faster. What is the explanation for this? Is there a way to write an equally fast implementation? – user1622959 Jan 26 '13 at 12:27
  • @user1622959 Probably because your P/Invoke call incurs some overhead. Make sure that you have called `RtlCopyMemory()` at least once before starting your benchmark to eliminate the time required to load the DLL and locate the requested symbol from the benchmark itself. Also try to ensure that you are not causing the array to be marshalled, as that could effectively double the time required to perform the P/Invoke call! – cdhowie Jan 28 '13 at 15:27
  • The benchmark is run twice and only the second time prints measurements, so DLL should be loaded and symbol located. I use fixed(int* ptr = array){...} and then pass the pointer to native, so I think there should not be any marshalling either. I seem to fail to reimplement other Marshal methods at a similar speed as well. My WriteInt32 can't keep up with the .NET implementation. The problem is, that .NET does not have WriteDecimal or WriteDateTime, so in the end, I have to be able to implement a fast version. – user1622959 Jan 29 '13 at 13:33
  • I'm not sure why that would be. At this point it's probably a good idea to open a new question, since we've strayed quite a bit from the original question. – cdhowie Jan 29 '13 at 15:27