Writing Unmanaged Functions for Microsoft .NET Compact Framework-based Applications

.NET Compact Framework 1.0

Content Master Ltd

April 2003

Applies to:
    Microsoft® .NET Compact Framework 1.0
    Microsoft Visual Studio® .NET 2003
    Microsoft eMbedded Visual C++® 3.0

Summary: Learn how to create unmanaged functions that you can use in your Smart Device applications through Platform Invoke. (4 printed pages)


Choosing an eMbedded Visual C++ 3.0 Project Type
Exporting Entry Points
Dealing with C++ Name Mangling
Type Marshaling
More Info


There will be occasions when writing Microsoft® .NET Compact Framework applications where you will need to call unmanaged code in order to interact directly with the underlying operating system. Interoperability between unmanaged and managed code in the .NET Compact Framework is a subset of full .NET Framework. For example, using delegates as callback functions is not supported by the .NET Compact Framework. Similarly, the .NET Compact Framework does not support full COM Interop, so if you want to access COM objects from the .NET Compact Framework, you must write an unmanaged module to act as a wrapper to handle the calls to the COM object and the type marshaling.

There are a few considerations to take into account when writing unmanaged code that is to be called from the managed world. This article covers these considerations and presents code for an unmanaged dynamic-link library (DLL).

This article assumes you are familiar with the eMbedded Visual C++ development environment and have an understanding of C++.

Choosing an eMbedded Visual C++ 3.0 Project Type

When using eVC++, you can choose to use either the WCE Dynamic-Link Library or the WCE MFC AppWizard (dll) project type. The former is used for simple DLL projects, while the latter is used for projects that need the functionality of the Microsoft Foundation Classes (MFC). To illustrate the main points about developing unmanaged DLLs for use with the .NET Compact Framework, this article will cover using the WCE Dynamic-Link Library project type.

Unlike managed code, which you compile once and which runs on any mobile device where the .NET Compact Framework runtime is installed, you must compile a separate DLL for each hardware platform you want to support. In the new project dialog box, you must choose the processors you wish to support in your DLL, and eVC++ will compile a separate build of the DLL for each selected processor platform. The eVC++ compiler is capable of supporting a variety of processors, including ARM, MIPS, SH and x86. It is important to remember that you will probably want to build an Intel x86 version of your DLL for use with the emulator.

Exporting Entry Points

Any function that can be called from outside the DLL must be marked as exported. In eVC++, this is done by prefixing the function declaration with _declspec(dllexport). It is also useful to mark your function declarations with the WINAPI calling convention, as this is the only calling convention supported by the .NET Compact Framework. The WINAPI macro maps to the __cdecl calling convention. Similarly, in the .NET Compact Framework, CallingConvention.Winapi is the managed equivalent of the WINAPI macro.

Below is an example of what a function declaration looks like in eVC++ when using the above techniques:

_declspec(dllexport) int WINAPI MyFunction(int MyVal)
    // Add implementation code here
    return 0;

Calling this from managed code, you would declare the unmanaged function in your code as follows:

public static extern int MyFunction(int MyVal);

Unfortunately, this call does not work as you would expect because of something called name mangling.

Dealing with C++ Name Mangling

Back in the early days of Windows, the object file format could not handle overloaded functions. To overcome this problem, the compiler generated unique names for each function, based upon its name and parameter list. This ensured that each function had a unique name for the linker. This unique naming came to be known as name mangling. The mangled form of MyFunction is something like ?MyFunction@@YAJXZ.

Name mangling presents a problem to the managed code that wishes to make a call to unmanaged code. Each compiler handles mangling in a different way, so it is difficult for you to know the exact name of an exported entry point. In C++, the extern "C" declaration can be used to force the compiler not to name mangle and to make the name of the exported function match that of the function in the source code.

Using the extern "C" declaration, a sample C++ function looks like this:

extern "C" _declspec(dllexport) int WINAPI multiply(int n1, int n2) 
    // Return the value of n1 and n2 multiplied together
    return(n1 * n2)

Type Marshaling

The .NET Compact Framework supports the conversion of simple types between managed and unmanaged code. Some types don't require any conversion. These are known as blittable types. The following table shows a list of blittable types with their managed and unmanaged equivalents.

C# Visual Basic .NET Native C/C++
Int Integer int
short Short short
bool Boolean BYTE
char Char WCHAR

You can also pass arrays, structures and classes to unmanaged code.

More Info

For additional information, please see the following resources: