J# was recently introduced and an article was included on it in MSDN Magazine. The author pointed out that, the J# libraries could be useful for other .NET languages. One reason was that, it included a number of fine classes such as
Compression and a library containing Win32 API function calls.
This article is primarily interested in the Win32 API. It turns out that accessing any of the J# libraries is flawed, if you care about performance. J# has no notions of many of the features we come to expect from C#, such as
ref parameters. Win32 data structures must be declared as
class; J# also use another helper class for each class to copy and pass the data to the Win32 API. Thus each call to a Win32 function is expensive because of the copying and memory allocation involved. In J#,
ref parameters are simulated by passing in a single element array. There are also a host of other inefficiencies.
Other .NET languages also include Win32 APIs declarations in some form. VB has the Win32API.txt file and Managed C++, of course, has the header files, but the C# does not have a corresponding library.
I created a new class library
Win32, with a default namespace of
Win32. That's right, I appropriated the name
Win32, because the class encapsulates Win32 function calls, constants and structures.
This is my first pass at the API class library. A new version will be arriving in days; I have released the Win32 API now for feedback.
Implemented in the
Win32 namespace are all the various Win32 structures (named in uppercase) such as
POINT, and so on. For example, this is what the
LOGFONT structure looks like. It is a top-level class underneath the
public struct LOGFONT
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
public byte lfFaceName;
structs are, by default, sequentially laid out, while classes are auto-laid out, but I should include the
SequentialLayout attribute as well, because the behavior is not specified in the standard. Some
structs should actually be explicitly laid out because of the presence of unions in them; but I haven't had time to do that yet.
There are few special classes such as
Shell and others. These classes contain all the Win32 API calls stemming from the system DLL of the same name. I have omitted the 32 suffix from
Shell32, because I felt they were redundant and unattractive.
public abstract class GDI
public static extern int AbortDoc(HDC hdc);
public static extern int AbortPath(HDC hdc);
public static extern int AddFontResource(string lpFileName);
public static extern int AngleArc(HDC hdc, int x, int y, int dwRadius,
double eStartAngle, double eSweepAngle);
public static extern int AnimatePalette(HANDLE hPalette,
int wStartIndex, int wNumEntries,
public static extern int Arc(HDC hdc, int X1, int Y1, int X2, int Y2,
int X3, int Y3, int X4, int Y4);
public static extern int ArcTo(HDC hdc, int X1, int Y1, int X2, int Y2,
int X3, int Y3, int X4, int Y4);
public static extern int BeginPath(HDC hdc);
public static extern int BitBlt(HDC hDestDC, int x, int y, int nWidth,
int nHeight, HDC hSrcDC, int xSrc, int ySrc, int dwRop);
public const int ABSOLUTE = 1;
public const int AD_CLOCKWISE = 2;
public const int AD_COUNTERCLOCKWISE = 1;
public const int ALTERNATE = 1;
public const int ANSI_CHARSET = 0;
public const int ANSI_FIXED_FONT = 11;
public const int ANSI_VAR_FONT = 12;
public const int ARABIC_CHARSET = 178;
public const int ASPECTX = 40;
public const int ASPECTXY = 44;
public const int ASPECTY = 42;
public const int ASPECT_FILTERING = 0x1;
The constants and structures are stable. Most of the changes overt the next week will occur to Win32 function signatures; however, most of them are correct right now even though they were changed through an automated process.
Some caution: I manually searched for function calls that should take a
StringBuilder in place of a
String. Any function that returns or modifies a string should be passing in a
StringBuilder. There may be other instances where I did not correctly use
ref keyword on a parameter of a primitive type. A function taking a non-
struct was assumed to be a
ref; I haven't really found a case where that was not true. (I will check again, since there are a few structures such as
COORD that can fit into a
A future modification will be more nuanced and distinguish between
ref parameters; for now, using a
ref parameter instead of an
out parameter will not produce negative consequences; however, the compiler will require a proper initialization of the structure before passing it into an API call.
Also included under the different DLL class (
GDI, ...) are all the constants that would naturally be categorized under that DLL whose name is that of the parent class.
I originally grouped constants in various enums whose name consisted of the prefix. So,
WM.PAINT, however, I felt that it might actually make it harder to find the desired constant, and it was also more work on my part. There were also issues about sub-constants, like
WM_DDE_ANY, should they be a
WM.DDE_ANY constant, a
WM.DDE.ANY constant, or a
WM.DDE_ANY constant. Well see, I have fully decided on this point.
Error codes are placed as constants within the abstract class
ERROR. I could use an
enum to store the values but this would require me to identify any call that returns an error code, but the benefit is that the compiler and debugger already knows how to display an
An alternative is to have Win32 methods that return error codes throw an exception. I plan on investigating this. For most API calls, I plan to merely return the error code value, but, some select API calls, I will throw an exception. This will depend on the performance requirements of call and severity of the error. For those functions that return error values and have a single
out parameter, I'll include a second variant that throws an exception and returns the
out parameter; those calls would have
PreservedSig set to
Over the next week, I will do the following:
- I plan to cross-check the library with VB's Win32API.txt, the C++ header files, the J# library and MSDN through some automated scripts.
- I also plan to introduce new types to match the handle types that Win32 uses; currently, handles are accepted as
IntPtr. My additions will provide a
HDC, and other value types that support conversions, equality and standard constants like
- I will overload certain API calls multiple types to allow for the range of possible data types accepted by Win32 calls. For example,
SendMessage can accept a wide variety of calls.
- I will also define delegates for the few
CALLBACK handlers that Win32 supports.
- I plan to place to include common COM interfaces as well into class library.
It's natural to wonder what the performance implications of having thousands of Win32 APIs methods declared in a library. I doubt there will be very much, but when the library is finally checked, I will conduct a performance analysis of introducing a large library where few functions are used. Since I have divided the library based on the DLL, it would be easy to remove those DLLs that you do utilize.
I believe this a worthy addition for Code Project and C# developers everywhere. Since this is a class library, it will work for other .NET languages. I do not include pointers or other non
CLSCompliant types in the Win32 API method signatures. Although for a few calls like
CopyMemory, I might actually add an additional overload with the (
false) attribute) that does accept pointers.
I would like to receive feedback to correct or restructure the library. If you had made noteworthy editions, I will do a diff and reapply to changes to my own copy, which I resubmit.
I would appreciate your vote.
- July 1, 2003 - Original article on Win32