March 3, 2021
Hot Topics:

Head-Spinning Continued: P/Invoke

  • By Kate Gregory
  • Send Email »
  • More Articles »

From Kate Gregory's Codeguru column, "Using Visual C++ .NET".

I'm continuing a series of columns on ways to access legacy C++ code from new managed C++ code. First I introduced you to the legacy class, which does arithmetic, and laid out the choices you have as a C++ programmer for interop. The second column wrapped the legacy class up as a COM component and accessed it from both unmanaged and managed code. But since COM Interop carries the largest performance penalty of all the choices, it should be used only when it's needed. There are other ways to run that old code from new code.

I introduced P/Invoke in this column almost a year ago, showing how to call some handy DLLs that you're sure to have on your machine, because they come with Windows (here). In this column I'll show how to wrap your legacy code into a DLL as well as how to call it from both managed and unmanaged code.

Creating a DLL

When you create a DLL in unmanaged C++, you can write a collection of global functions, or you can write member functions of one or more classes. If you're calling it from unmanaged C++, writing a class and its member functions is an excellent choice. You need to keep in mind, though, that C++ functions are decorated (mangled) with information about the parameters they take and the class they are in. This is invisible when you use the DLL from another unmanaged application, but a bit of a problem when calling from managed code. It's simpler if your DLL contains only global functions, which you can mark with extern "C" to prevent decoration. You don't have to throw away your object-oriented approach: write one DLL for each class, and have the member functions of the class as global functions in that DLL.

If you adopt this approach for a large and complex system, remember that you don't have to convert your old code to a DLL: you can write a new DLL that offers certain services, and that calls your old code to implement those services. This simpler facade can use classes from your existing library and simply wrap the functionality into the DLL. In this sample, I'll implement Add right in the DLL, just because it's so simple.

I created a new Win32 project and set the application type to DLL. Then I coded the Add() function:

extern "C" __declspec(dllexport) 
double Add(double num1, double num2)
   return num1 + num2;

The extern "C" prevents name decoration, which is normally applied even to global functions. The __declspec(dllexport) indicates to the compiler that this function is to be exported from the DLL. The rest of the function is straightforward: in a more complex system this would be a wrapper function that calls methods of other classes or functions in another DLL.

Page 1 of 2

This article was originally published on August 26, 2003

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date