PageRenderTime 9ms CodeModel.GetById 1ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/Visual Studio 2008/CSPInvokeDll/Program.cs

#
C# | 159 lines | 58 code | 26 blank | 75 comment | 2 complexity | 67c02e7decc5d28c58043f7724d8825a MD5 | raw file
  1/****************************** Module Header ******************************\
  2* Module Name:  Program.cs
  3* Project:      CSPInvokeDll
  4* Copyright (c) Microsoft Corporation.
  5* 
  6* Platform Invocation Services (P/Invoke) in .NET allows managed code to call 
  7* unmanaged functions that are implemented and exported in unmanaged DLLs.  
  8* This VC# code sample demonstrates using P/Invoke to call the functions 
  9* exported by the native DLLs: CppDynamicLinkLibrary.dll, user32.dll and 
 10* msvcrt.dll.
 11* 
 12* This source is subject to the Microsoft Public License.
 13* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
 14* All other rights reserved.
 15* 
 16* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
 17* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
 18* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 19\***************************************************************************/
 20
 21#region Using directives
 22using System;
 23using System.Runtime.InteropServices;
 24#endregion
 25
 26
 27namespace CSPInvokeDll
 28{
 29    class Program
 30    {
 31        static void Main(string[] args)
 32        {
 33            bool isLoaded = false;
 34            const string moduleName = "CppDynamicLinkLibrary";
 35
 36            // Check whether or not the module is loaded.
 37            isLoaded = IsModuleLoaded(moduleName);
 38            Console.WriteLine("Module \"{0}\" is {1}loaded", moduleName, 
 39                isLoaded ? "" : "not ");
 40
 41            //
 42            // Access the global data exported from the module.
 43            // 
 44
 45            // P/Invoke does not allow you to access the global data exported 
 46            // from a DLL module.
 47
 48            //
 49            // Call the functions exported from the module.
 50            //
 51
 52            string str = "HelloWorld";
 53            int length;
 54
 55            length = NativeMethod.GetStringLength1(str);
 56            Console.WriteLine("GetStringLength1(\"{0}\") => {1}", str, length);
 57
 58            length = NativeMethod.GetStringLength2(str);
 59            Console.WriteLine("GetStringLength2(\"{0}\") => {1}", str, length);
 60
 61            // P/Invoke the stdcall API, MessageBox, in user32.dll.
 62            MessageBoxResult msgResult = NativeMethod.MessageBox(
 63                IntPtr.Zero, "Do you want to ...", "CSPInvokeDll", 
 64                MessageBoxOptions.OkCancel);
 65            Console.WriteLine("user32!MessageBox => {0}", msgResult);
 66
 67            // P/Invoke the cdecl API, printf, in msvcrt.dll.
 68            Console.Write("msvcrt!printf => ");
 69            NativeMethod.printf("%s!%s\n", "msvcrt", "printf");
 70
 71            // 
 72            // Call the callback functions exported from the module.
 73            // 
 74
 75            // P/Invoke a method that requires callback as one of the args.
 76            CompareCallback cmpFunc = new CompareCallback(CompareInts);
 77            int max = NativeMethod.Max(2, 3, cmpFunc);
 78
 79            // Make sure the lifetime of the delegate instance covers the 
 80            // lifetime of the unmanaged code; otherwise, the delegate 
 81            // will not be available after it is garbage-collected, and you 
 82            // may get the Access Violation or Illegal Instruction error.
 83            GC.KeepAlive(cmpFunc);
 84            Console.WriteLine("Max(2, 3) => {0}", max);
 85
 86            //
 87            // Use the class exported from the module.
 88            //
 89
 90            // There is no easy way to call the classes in a native C++ DLL 
 91            // module through P/Invoke. Visual C++ Team Blog introduced a 
 92            // solution, but it is complicated: 
 93            // http://go.microsoft.com/?linkid=9729423.
 94            // The recommended way of calling native C++ class from .NET are  
 95            // 1) use a C++/CLI class library to wrap the native C++ module, 
 96            //    and your .NET code class the C++/CLI wrapper class to 
 97            //    indirectly access the native C++ class.
 98            // 2) convert the native C++ module to be a COM server and expose
 99            //    the native C++ class through a COM interface. Then, the 
100            //    .NET code can access the class through .NET-COM interop.
101
102            // Unload the DLL by calling GetModuleHandle and FreeLibrary. 
103            if (!FreeLibrary(GetModuleHandle(moduleName)))
104            {
105                Console.WriteLine("FreeLibrary failed w/err {0}", 
106                    Marshal.GetLastWin32Error());
107            }
108
109            // Check whether or not the module is loaded.
110            isLoaded = IsModuleLoaded(moduleName);
111            Console.WriteLine("Module \"{0}\" is {1}loaded", moduleName, 
112                isLoaded ? "" : "not ");
113        }
114        
115        /// <summary>
116        /// This is the callback function for the method Max exported from 
117        /// the DLL CppDynamicLinkLibrary.dll.
118        /// </summary>
119        /// <param name="a">the first integer</param>
120        /// <param name="b">the second integer</param>
121        /// <returns>
122        /// The function returns a positive number if a > b, returns 0 if a 
123        /// equals b, and returns a negative number if a &lt b.
124        /// </returns>
125        static int CompareInts(int a, int b)
126        {
127            return (a - b);
128        }
129
130
131        #region Module Related Operations
132
133        /// <summary>
134        /// Check whether or not the specified module is loaded in the 
135        /// current process.
136        /// </summary>
137        /// <param name="moduleName">the module name</param>
138        /// <returns>
139        /// The function returns true if the specified module is loaded in 
140        /// the current process. If the module is not loaded, the function 
141        /// returns false.
142        /// </returns>
143        static bool IsModuleLoaded(string moduleName)
144        {
145            // Get the module in the process according to the module name.
146            IntPtr hMod = GetModuleHandle(moduleName);
147            return (hMod != IntPtr.Zero);
148        }
149
150        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
151        static extern IntPtr GetModuleHandle(string moduleName);
152
153        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
154        [return: MarshalAs(UnmanagedType.Bool)]
155        static extern bool FreeLibrary(IntPtr hModule);
156
157        #endregion
158    }
159}