Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for organizing .NET P/Invoke code to Win32 APIs

I am refactoring a large and complicated code base in .NET that makes heavy use of P/Invoke to Win32 APIs. The structure of the project is not the greatest and I am finding DllImport statements all over the place, very often duplicated for the same function, and also declared in a variety of ways:

The import directives and methods are sometimes declared as public, sometimes private, sometimes as static and sometimes as instance methods. My worry is that refactoring may have unintended consequences but this might be unavoidable.

Are there documented best practices I can follow that can help me out?

My instict is to organize a static/shared Win32 P/Invoke API class that lists all of these methods and associated constants in one file... EDIT There are over 70 imports to the user32 DLL.

(The code base is made up of over 20 projects with a lot of windows message passing and cross-thread calls. It's also a VB.NET project upgraded from VB6 if that makes a difference.)

like image 616
Paul Sasik Avatar asked Mar 12 '10 16:03

Paul Sasik


People also ask

What overarching namespace provides PInvoke to net?

Most of the P/Invoke API is contained in two namespaces: System and System. Runtime.

How does PInvoke work?

P/Invoke is the technique a programmer can use to access functions in these libraries. Calls to functions within these libraries occur by declaring the signature of the unmanaged function within managed code, which serves as the actual function that can be called like any other managed method.

What is PInvoke net?

PInvoke.net is primarily a wiki, allowing developers to find, edit and add PInvoke* signatures, user-defined types, and any other information related to calling Win32 and other unmanaged APIs from managed code (written in languages such as C# or VB.NET).


2 Answers

You might consider the way it was done in the .NET framework. It invariably declares a static class (Module in VB.NET) named NativeMethods that contains the P/Invoke declarations. You could be more organized than the Microsoft programmers, there are many duplicate declarations. Different teams working on different parts of the framework.

However, if you want to share this among all projects you have to declare these declarations Public instead of Friend. Which isn't great, it ought to be an implementation detail. I think you can solve that by re-using the source code file in every project that needs it. Normally taboo but okay in this case, I think.

I personally declare them as needed in the source code file that needs them, making them Private. That also really helps when lying about the argument types, especially for SendMessage.

like image 58
Hans Passant Avatar answered Sep 28 '22 22:09

Hans Passant


Organize them into a [Safe|Unsafe]NativeMethods class. Mark the class as internal static. If you need to expose them to your own assemblies, you can use InternalsVisibleTo - though it'd be more appropriate if you could group related ones into each assembly.

Each method should be static - I honestly wasn't aware you could even mark instance methods with DllImport.

As a first step - I'd probably move everything to a Core assembly (if you have one), or create a Product.Native assembly. Then you can find dupes and overlaps easily, and look for managed equivalents. If your p/invokes are a mess, I don't suspect you have much in the way of layering in the other assemblies that will guide your grouping.

like image 35
Mark Brackett Avatar answered Sep 28 '22 22:09

Mark Brackett