And here was I, hoping that C# interop did finally solve the problem around name mangling and supports importing C++ classes. However, thank you for the new P/Invoke stuff. It's really helpful.
There are many performance pitfalls indeed, especially on regards to memory management. Regarding CPU: looking up the native method addresses and invoking them doesn't have much of a performance cost, but how you structure your interop "API" could make an impact.
Yes there are pitfalls and there's much to learn. I've encountered native interop in hardware drivers, image processing libraries and the UnityEngine. What high performance libraries do is keep the majority of data in native space and use handles to work with them. Those may be pointers but may be just unique numbers that represent something. Like you load an image file or open a device and get a handle to it and in other operations, you pass that handle. There's a little overhead in the pInvoke but the biggest loss is in marshalling. Unity's biggest problem for example is that strings can not be blitted. Blitting is when you can copy the whole data structure. C# strings have a prefix that contains the length while C-strings end with a \0 terminator (well, some do...), and there's the individual character encoding. The microsoft article for "Blittable and Non-Blittable Types" is worth reading if you want to know more. As always, the processor fast, accessing memory is slow, so everything stack based is great, that's why i am so hyped about stackalloc which allows to pass sweet little pieces of stack memory instead of having to pass pointers to heap memory. Also the dotnet GC can move memory to prevent memory fragmentation, which means the pointers passed to native code may become invalid, that's why 'pinning' exists, which marks objects as "don't move that around please", which comes at a cost, but in many cases is much smaller than copying a whole array or a huge data structure. ILSpy and dnSpy are great tools to look into libraries and see how their internals work.
A pipe dream, but sometimes I wish Microsoft would port C++/CLI to be cross platform. The front end of MSVC comes to Linux/MacOS, but use LLVM as the backend. Yes, not a trivial thing, but a programmer can dream.
And here was I, hoping that C# interop did finally solve the problem around name mangling and supports importing C++ classes. However, thank you for the new P/Invoke stuff. It's really helpful.
Very informative, great talk Justin! We're proud to have a member of the team speak at .NET Conf 2024.
I would love to have a video on this topic, but focused on performance as I'm sure there are many pitfalls and nuances that might affect it greatly.
There are many performance pitfalls indeed, especially on regards to memory management.
Regarding CPU: looking up the native method addresses and invoking them doesn't have much of a performance cost, but how you structure your interop "API" could make an impact.
Yes there are pitfalls and there's much to learn.
I've encountered native interop in hardware drivers, image processing libraries and the UnityEngine. What high performance libraries do is keep the majority of data in native space and use handles to work with them. Those may be pointers but may be just unique numbers that represent something.
Like you load an image file or open a device and get a handle to it and in other operations, you pass that handle.
There's a little overhead in the pInvoke but the biggest loss is in marshalling. Unity's biggest problem for example is that strings can not be blitted. Blitting is when you can copy the whole data structure. C# strings have a prefix that contains the length while C-strings end with a \0 terminator (well, some do...), and there's the individual character encoding.
The microsoft article for "Blittable and Non-Blittable Types" is worth reading if you want to know more.
As always, the processor fast, accessing memory is slow, so everything stack based is great, that's why i am so hyped about stackalloc which allows to pass sweet little pieces of stack memory instead of having to pass pointers to heap memory. Also the dotnet GC can move memory to prevent memory fragmentation, which means the pointers passed to native code may become invalid, that's why 'pinning' exists, which marks objects as "don't move that around please", which comes at a cost, but in many cases is much smaller than copying a whole array or a huge data structure.
ILSpy and dnSpy are great tools to look into libraries and see how their internals work.
A pipe dream, but sometimes I wish Microsoft would port C++/CLI to be cross platform. The front end of MSVC comes to Linux/MacOS, but use LLVM as the backend. Yes, not a trivial thing, but a programmer can dream.
Is there one for rust?