first_page the funky knowledge base
personal notes from way, _way_ back and maybe today

MCAD/MCSD Notes: Chapter 7, Lesson 2; Using Unmanaged Code

Lesson 2: Using Unmanaged Code

The purpose of this lesson is to highlight the backwards-compatibility features of the .NET Framework, it's ability to create static entry points into Win32 COM interfaces. This lesson is quite forthcoming about the limitations of these features.

The "native code" is usually in the form of a COM DLL (of "DLL Hell" infamy). These are called by declaring the System.Runtime.InteropServices.DllImportAttribute as in the lesson's code sample:

[DllImport("KERNEL32.DLL", ...)]...

When "invoking" the Win32 platform, data is exchanged between the .NET Framework and the Win32 API in the form of passing parameters and reading results. This data exchange is often in the form of custom types defined by data structures.

This is the System.Runtime.InteropServices.StructLayoutAttribute with the form:

[StructLayout(LayoutKind.Sequential)]...

This lesson may suggest that the reason why struct (in C#) and Structure (in VB.NET) exist in .NET languages is to facilitate structured data exchange between the .NET Framework and the Win32 API. It definitely suggests in the code samples that Class definitions (with all public fields) can also be used instead of struct types.

Discovering exactly what data needs to be structured and passed into the Win32 API is no trivial task. For more information, please see:

"Marshaling Data with Platform Invoke"
http://msdn.microsoft.com/library/en-us/cpguide/
    html/cpconmarshalingdatawithplatforminvoke.asp

"P/Invoke (Platform Invoke) links and resources"
http://dotnetjunkies.com/WebLog/imranko/archive/2004/10/24/29558.aspx

"Platform Invoke Cheat Sheet"
http://www.gotdotnet.com/team/clr/bcl/TechArticles/
   TechArticles/PInvokeHelp/FAQ.aspx

The lesson's code sample used to illustrate the use of Marshal.GetLastWin32Error() does not recognize the existence of the System.ComponentModel.Win32Exception type. With this recognition the code can refactored as:

// MoveTo returns False if there is an error.
Win32Exception ex = new Win32Exception(Marshal.GetLastWin32Error());
string msg = ex.Message;

instead of this:

// MoveTo returns False if there is an error.
string msg ;
// Set a message depending on error code returned.
switch (Marshal.GetLastWin32Error())
{
    case 2:
        msg = "File not found.";
        break;
    case 3:
        msg = "Path not found.";
        break;
    case 5:
        msg = "Access denied.";
        break;
    case 15:
        msg = "Drive not found.";
        break;
    default:
        msg = "Unlisted error.";
        break;
}

This performance limitation seems to be most surprising limitation of p-invoke. The others, "type safety," "versioning" and "code security" are to be expected.

mod date: 2005-06-30T00:20:27.000Z