Head-Spinning Continued: Who needs P/Invoke?

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

From Kate Gregory’s Codeguru column, “Using Visual C++ .NET“.

–>

If you wander over to Google and try a search like “DLL managed code” you will find page after page about P/Invoke. From VB or C#, that’s the only way to access a DLL. But, as I said in my very first column here at CodeGuru, C++ is special.

One of the things that make it special is It Just Works technology; calling unmanaged code from managed code without any special attributes, flags, options, or, well anything actually. Let’s take the example we’ve been working with during this series of columns: the class that does arithmetic. In my last column we turned it into a DLL and got to it through P/Invoke. Because it uses only fundamental types (doubles in this case) there was no need for any special marshaling. The DllImport attribute existed only to provide the name of the DLL where the function could be found.

In that case, who needs it? The DLL came with an import library, a .LIB file that you can link into your application. When you write an unmanaged application, you link to the import library, and at run time the DLL is implicitly loaded and run. You arrange this by adding the name of the library to the Additional Dependencies property of the project (On the Input page under Linker in the properties page for the project.) Well when you write a managed application, it’s no different: you can still just link to the import library.

I copied the project from last column to another folder. Remember the DLL had been copied into the project folder already. I just copied the import library in there too, and made two changes. First, I ripped the DllImport attribute off the declaration of Add(), though I left the declaration in place:

extern "C" {
double Add(double num1, double num2);
}

Then I added the import library to the linker dependencies. This code works beautifully — it’s an irresistible temptation to point out that It Just Works.

So What’s the Difference?

The sample application can use the Add() function from the DLL whether you go through P/Invoke or not. The call looks exactly the same in code, and the effort-level of typing the DllImport attribute versus setting a linker property are equivalent. So how do you choose between them?

First, not all DLLs come with import libraries. If you made the DLL yourself as part of reusing legacy code, or if the DLL happened to come with an import library, then you have this option. If the DLL came from another source, you may not have the choice.

Secondly, using P/Invoke gives you control over marshaling and conversions, including string conversions, with little or no effort on your part. If the DLL parameters need to be manipulated as part of every call (for example, converting a System::String to a char*) then P/Invoke is a good choice.

Third, accessing unmanaged code through P/Invoke requires less than FullTrust permission. Chances are, your application needs FullTrust anyway, so as to get SkipVerification, as I discussed in the first column of this series. But if youve gone through all those hoops to enable your code to be verified, using P/Invoke will keep you verifiable.

So why would anyone use It Just Works instead of P/Invoke? Two reasons, one better than the other. The first is psychological: you don’t have to learn anything new. Just do what you used to do — link to the import library, declare the functions (you can even use the old header files with the declspecs in them; the declspec will be ignore) and call them. The second is performance. The stack walking, security checking, marshaling and so on provided by P/Invoke have a small performance cost associated with them. If you get no benefit from them, why pay the cost? IJW is quicker than P/Invoke, so if you can use it, go ahead and use it.

Next time, I’m going to take this It Just Works concept one step further, and just recompile the legacy code as managed code with unmanaged data, and discuss the pros and cons of that approach.

About the Author

Kate Gregory is a founding partner of Gregory Consulting Limited (www.gregcons.com). In January 2002, she was appointed MSDN Regional Director for Toronto, Canada. Her experience with C++ stretches back to before Visual C++ existed. She is a well-known speaker and lecturer at colleges and Microsoft events on subjects such as .NET, Visual Studio, XML, UML, C++, Java, and the Internet. Kate and her colleagues at Gregory Consulting specialize in combining software develoment with Web site development to create active sites. They build quality custom and off-the-shelf software components for Web pages and other applications. Kate is the author of numerous books for Que, including Special Edition Using Visual C++ .NET.


# # #

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read