[HN Gopher] Microsoft Opens Up Old Win32 APIs to C# and Rust
       ___________________________________________________________________
        
       Microsoft Opens Up Old Win32 APIs to C# and Rust
        
       Author : rsecora
       Score  : 66 points
       Date   : 2021-01-23 19:14 UTC (3 hours ago)
        
 (HTM) web link (visualstudiomagazine.com)
 (TXT) w3m dump (visualstudiomagazine.com)
        
       | logbiscuitswave wrote:
       | Clickbait title isn't really accurate. You've always had this
       | ability by using P/Invokes, but it's never been easy. It requires
       | a lot of domain knowledge (or copy-pasta that may cause other
       | problems) to actually get it to work. It's also very easy to get
       | wrong and cause big memory leaks in the unmanaged heap.
       | 
       | Over the years I've managed to get pretty good at P/Invokes to
       | the point where I don't bat an eye when I need to do some interop
       | with native code. That doesn't mean I don't sometimes run into a
       | particularly finicky API that requires digging deep into stuff
       | like GC pinning, structure packing, fixed pointers, or other
       | challenges that will grind things to a halt while I debug what's
       | happening. At least I've come to the point where I can look at
       | unexpected API behavior and have a good intuition for what I need
       | to do.
       | 
       | It sucks, a lot.
       | 
       | I'm really glad that there's finally an official and reusable
       | abstraction to make this simpler in the future.
        
         | kerng wrote:
         | I do remember depending on the site pinvoke.net quite a bit in
         | the past - but yeah this was always possible with C#. It was
         | even what made J++ (Microsoft's Java, before it became C#)
         | unique compared to Sun's version in the 90s, as it allowed this
         | kind of tight Windows integration also if I recall correctly.
        
           | sedatk wrote:
           | Didn't JNI allow that kind of integration?
        
             | int_19h wrote:
             | JNI is a bit different - you have to write code in C or C++
             | that wraps native APIs you want to call, in a certain very
             | specific way that then makes it possible to call it via
             | methods declared as "native" in Java.
             | 
             | P/Invoke does not require such a layer - you simply declare
             | enums, structs, and functions from the native API directly
             | in your C# code, and then you can call them.
             | 
             | For those familiar with Python, the Java way is more like
             | writing a Python extension module in C, and the C# way is
             | more like using ctypes (but way faster).
             | 
             | Java has some third party libraries that are basically
             | P/Invoke equivalent; JNA is probably the most used one.
        
             | DaiPlusPlus wrote:
             | I think it was because MS' Java's standard libraries
             | included Java wrappers over Win32 already, so programming
             | beginners in Java can make "real"-looking Windows desktop
             | GUI applications without knowing any C or at least knowing
             | how to read *.h files and translate them to Java.
        
             | josefx wrote:
             | Microsoft had RNI which was comparable to JNI and could be
             | used to write native code. It also had J/Direct which could
             | be used to bind existing native code to a Java method
             | declared native with only a comment, the closest to that
             | for standard Java that I know of is JNA and apparently that
             | wasn't around until 2007?
        
           | sn_master wrote:
           | It was also possible in VB6, planet-source-code was the best
           | source for that..
        
         | yread wrote:
         | P/Invoke is not that bad - you basically just copy the c header
         | declaration and adjust a bit. It starts to be interesting
         | strings or large memory where you want to avoid copying it too
         | much. Doing it cross-platform is a bit of pain (basically copy
         | everything and point it to different library - .dll vs .so) it
         | would be nice if there was a better way. I still haven't
         | figured out how to get unicode strings to work cross platform
         | though.
        
           | int_19h wrote:
           | One trick is to avoid smart marshaling (for C# strings,
           | arrays etc), and use "unsafe" and raw pointers. This way, all
           | your types are what CLR calls blittable - i.e. their
           | representation is the same in native and managed - and the
           | behavior is straightforward and predictable, as no copying or
           | implicit conversions occur. This is particularly useful for
           | cases when you have something like a struct containing a
           | pointer to a struct containing a string, and when ownership
           | of memory is unclear.
           | 
           | Of course, the downside is that you have to do all the
           | marshaling yourself then. E.g. for strings, you use the
           | appropriate System.String constructor to create one from a
           | raw pointer - it has overloads for null-terminated string
           | pointers as well as pointer + length, and you can specify
           | encoding too. Or, to pass the string to native, you pin it
           | using "fixed" to obtain a pointer.
        
         | sandermvanvliet wrote:
         | My approach has always been to create a separate dll (written
         | in C++) that wraps all the complicated stuff and has only a few
         | calling points exposed which were P/Invoked from the C# side.
         | Haven't had to do much of this but that definitely saved me
         | from doing a lot of clunky stuff in the C# app
        
         | spaetzleesser wrote:
         | I am pretty good about writing P/Invokes but I have no way of
         | proving that what I did won't create some memory overwrite or
         | leak. Too many moving parts between C# and C++. Nowadays I find
         | it better to write a layer in managed C++. This seems much
         | safer and in a sense is more straightforward.
        
       | simplicio wrote:
       | The first two paragraphs are wrong, aren't they? My understanding
       | is that the "32" in Win32 was originally to distinguish 32 bit
       | from 16 bit API calls, but now its just the generic name for the
       | Windows API.
       | 
       | The article makes it sound like the change is only of interest if
       | you're compiling 32-bit applications.
        
         | jarjoura wrote:
         | Win32 is the consistent branding Microsoft has used to describe
         | its C/C++ API for the last 20 years. It's many things though,
         | GDI, User32, NT, DirectX, etc.
        
           | int_19h wrote:
           | It's no longer true because of WinRT - which also has a C/C++
           | API, but is not considered Win32.
        
         | OnlyOneCannolo wrote:
         | It's an error of omission in that Win32 also refers to the
         | 64-bit versions. The Windows API includes but is not limited to
         | Win32.
         | 
         | https://docs.microsoft.com/en-us/windows/win32/
        
           | simplicio wrote:
           | Yea, that was my understanding. But its not an error of
           | omission, the article specifically stresses its the API _for
           | 32 bits_ twice in the first two sentences of the article.
        
             | OnlyOneCannolo wrote:
             | They're wrong because they didn't realize they left
             | something out of a partially true statement. That's an
             | error of omission.
        
               | Dylan16807 wrote:
               | "Win32 APIs long used for 32-bit Windows programming" is
               | omission.
               | 
               | "Win32 is the 32-bit API" is flat-out wrong.
        
               | OnlyOneCannolo wrote:
               | Win32 refers to the 32-bit API and 64-bit API, so it's
               | correct to call it a 32-bit API.
               | 
               | The article never explicitly said that Win32 is
               | exclusively 32-bit, so it omitted 64-bit.
        
       | jarjoura wrote:
       | There is a performance penalty when accessing APIs over WinMD and
       | that is acceptable when you're only using them sparingly. I'd be
       | curious how using Win32 APIs over WinMD performs instead of using
       | PInvoke or FFI.
       | 
       | Edit: Here is the actual project if anyone is interested in
       | following along. https://github.com/microsoft/win32metadata/
        
         | WalterGR wrote:
         | > There is a performance penalty when accessing APIs over WinMD
         | 
         | Specifically when using WinMD? Why?
         | 
         | Or do you mean vs. calling the APIs directly via C code, or vs.
         | using in-language techniques such as P/Invoke?
        
         | int_19h wrote:
         | It only uses WinMD as the format for metadata input for code
         | generation. The output for C# is still a bunch of P/Invoke
         | declarations (using Roslyn source generators).
         | 
         | By the way, .NET is also retiring the ability to use WinMD
         | directly via runtime projection, in favor of code generation:
         | https://github.com/microsoft/CsWinRT
        
       | 29athrowaway wrote:
       | For widgets and windows... I prefer to use GTK, which has a much
       | easier learning curve, and works on multiple platforms, and works
       | well with HiDPI.
       | 
       | Win32 uses hungarian notation, which is not common these days.
       | The thing was designed for a time in which programming tools had
       | almost no autocompletion and were slightly better than a text
       | editor.
        
       | rkagerer wrote:
       | This may be several years late but is nonetheless great news!
        
       | userbinator wrote:
       | It's funny to see MS do this after all those years of messing
       | around with various other bloaty UI frameworks... and further
       | reaffirms my decision to stay with pure Win32.
       | 
       | Perhaps MS is encouraging developers to native UI after all.
        
         | int_19h wrote:
         | WinRT is not going anywhere. What more, it's usable from
         | classic Win32 apps these days.
         | 
         | https://github.com/microsoft/ProjectReunion
        
           | userbinator wrote:
           | _The software may collect information about you and your use
           | of the software and send it to Microsoft._
           | 
           | The "new Microsoft" is still there for sure...
        
       | [deleted]
        
       ___________________________________________________________________
       (page generated 2021-01-23 23:01 UTC)