Using Managed and Unmanaged C DLLs in Your .NET Programs

I l @ ve RuBoard

Using Managed and Unmanaged C++ DLLs in Your .NET Programs

Dynamic library linkage and use is simple using managed extensions for C++ under .NET. C++ DLLs compiled to IL, like their native .NET language counterparts, are tagged with metadata that provides the calling program information about the classes and methods stored in the DLL. This means that you can use them just like ordinary .NET objects written in C# or VB.

Other DLLs that you might use, such as the system DLLs or those you create, require a little more work but are still straightforward thanks to the Interop services provided by the Common Language Runtime.

Listing 1.4.11 shows a managed C++ component that will be compiled as a DLL.

Listing 1.4.11 cppdll.cpp : A Simple Managed C++ DLL
 #using <mscorlib.dll> using namespace System; using namespace System::Text; using namespace System::IO; // This is a managed C++ DLL that uses .Net framework classes // compile with... // cl /CLR /LD cppdll.cpp namespace cppdll { //Demonstrates calling a class method.... public __gc class AClass { public:     void FirstMethod(int n)     {         String* pS=S"Hi from Firstmethod  ";         StringBuilder* pB=new StringBuilder(pS);         StringWriter* pW=new StringWriter(pB);         for(int x=n;x>=0;x--)         {             pW->Write(__box(x));             if(x)                 pW->Write(S", ");             else                 pW->Write(S"...");         }         pS=pW->ToString();         Console::WriteLine(pS);     } }; } 

Type in this code and save it as cppdll.cpp . Then compile it with this command line:

 cl /CLR /LD cppdll.cpp 

This DLL will be called as if it were a simple .NET managed object.

Listing 1.4.12 shows a standard unmanaged C++ DLL that performs a function equivalent to the C# DLL we created in Listing 1.4.9. As you can see, it has a standard DllMain function and a DllFunction that can be called to do some processing and print a message.

Listing 1.4.12 straightdll.cpp : A Simple x86 DLL
 // This is a straight C++ DLL that will be called using the p-invoke // system interop services from .NET #include <windows.h> #include <stdio.h> #include <string.h> static char *buffer; char* __stdcall DllFunction(int n) {     sprintf(buffer,"Hi From DllFunction! ");     for(int x=n;x>=0;x--)     {         char temp[100];         sprintf(temp,"%d%s",x,(x==0 ? "..." : ", "));         strcat(buffer,temp);     }     return &buffer[0]; } BOOL __stdcall DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID resvd) {     switch(dwReason)     {         case DLL_PROCESS_ATTACH:             buffer = (char *)malloc(1000);             memset(buffer,0,1000);             printf("Straightdll loaded\ n");             return TRUE;         case DLL_PROCESS_DETACH:             free(buffer);             printf("Straightdll unloaded\ n");             return TRUE;         default:             return FALSE;     } } 

The following is the old-style DEF file that is used to export the functions from the DLL.

 EXPORTS     DllFunction @1     DllMain @2 

Type to a file and save straightdll.def , then build the DLL with the following command line:

 cl /LD straightdll.cpp /link /DEF:straightdll.def 

These DLLs can both be used by C# or VB programs that you write. This ability to call old-style DLLs with new-style code or languages maintains your investment in legacy code, applications, and tools as you make the transition to .NET. For this demonstration, we will write a very simple C# program that shows how to use the managed C++ class and the unmanaged DLL. Listing 1.4.13 shows the code for the host executable cppdllusr.exe .

Listing 1.4.13 cppdllusr.cs : A Simple C# Program Showing DLL Use
 1: using System; 2: using System.Text; 3: using System.IO; 4: using System.Runtime.InteropServices; 5: 6: using cppdll; 7: 8: class dlltester 9: { 10: 11:     [DllImport("straightdll.dll")] 12:     [return:MarshalAs(UnmanagedType.LPStr)] 13:     public static extern String DllFunction(int n); 14: 15:     static void Main() 16:     { 17: 18:         // First the method in the C++ dll cppdll.dll" is invoked... 19:         AClass pC=new AClass(); 20:         pC.FirstMethod(10); 21: 22:         //Now to invoke the wrapper function for the unmanaged DLL 23:         Console.WriteLine(DllFunction(10)); 24: 25:     } 26: } 

Using the managed C++ DLL is straightforward, but the unmanaged one is more complex. Let's examine the part that makes interaction with unmanaged code possible.

The code on lines 11, 12, and 13 in Listing 1.4.13 shows how to create a wrapper for a function in an unmanaged DLL. This uses attributes to create a proxy for the unmanaged code and to marshal the parameters and return types to and from the unmanaged part of the system.

The attribute [DllImport(...)] specifies that the following function signature is one exported by the named DLL, in this case straightdll.dll , which we created in Listing 1.4.11. This function returns a char * to a buffer that it allocates . The managed runtime, however, will require the returned data to be packaged in a more .NET-friendly object, so instead of using char * as the return type for our function, we use String and tell the system that it needs to marshal the data when it returns from the function. This is accomplished with the [return:MarshalAs(...)] attribute. Its position before the function declaration signifies that it is the return type that is to be marshaled. The same attribute could be used on a parameter to transfer data from a string to a char * . The argument to the MarshalAs attribute is one of a list of recognized types from the System::Runtime::InteropServices namespace.

The invocation of the DllFunction is on line 23. It's a simple argument to the Console.WriteLine method. This accepts only System.Object -based items, so you can see that the marshaling of the returned char * to a String object has taken place.

Type Listing 1.4.13 into a file called cppdllusr.cpp and compile it using the following command line:

 csc /r:cppdll.dll cppdllusr.cs 

The program will compile, and you can run cppdllusr from the command line.

I l @ ve RuBoard


C# and the .NET Framework. The C++ Perspective
C# and the .NET Framework
ISBN: 067232153X
EAN: 2147483647
Year: 2001
Pages: 204

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net