title: Loading a C++ DLL in C#
body: <p>I am trying to use a DLL that was writen in C++ but my application is in C#</p>
  
  <p>The DLL is from another company but they have supplied an SDK for their software.</p>
  
  <p>They give an example of how to load their DLL in C++ but I need to adapt it to C#.</p>
  
  <p>Below is their instructions of how to do it in C++</p>
  
  <p>MarkEzd.dll file is Dynamic Link Library.</p>
  
  <p>MarkEzdDll.h is header file of the exports function in MarkEzd.dll</p>
  
  <p>The calling way of MarkEzd.dll is explicitly link. Developer needs to load and free MarkEzd.dll by calling Windows API function.</p>
  
  <p>The steps are as follows.</p>
  
  <ol>
  <li><p>Call Windows’ API function LoadLibrary() to load DLL dynamically; </p></li>
  <li><p>Call Windows’ API function GetProcAddrress() to get the pointer of the functions in the DLL and use the function pointer to finish the work;</p></li>
  <li><p>Call Windows’ API function FreeLibrary() to release library when you do not use DLL or the program ends.</p></li>
  </ol>
  
  <p>Below is the example they have provided.</p>
  
  <p>Step 2.  Program software for calling markezd.dll.
  a)  First step : Dynamic Load MarkEzd.dll</p>
  
  <pre><code>HINSTANCE hEzdDLL = LoadLibrary(_T("MarkEzd.dll"));
  </code></pre>
  
  <p>b)  Second step:  get the pointer of the function to be called</p>
  
  <pre><code>lmc1_Initial=(LMC1_INITIAL)GetProcAddress(hEzdDLL, _T("lmc1_Initial"));
  lmc1_Close=(LMC1_CLOSE)GetProcAddress(hEzdDLL, _T("lmc1_Close"));
  lmc1_LoadEzdFile=(LMC1_LOADEZDFILE)GetProcAddress(hEzdDLL,_T("lmc1_LoadEzdFile"));  
  lmc1_Mark=(LMC1_MARK)GetProcAddress(hEzdDLL,_T("lmc1_Mark"));
  </code></pre>
  
  <p>c)  Third step: Call the function</p>
  
  <p>1）    Initialization lmc1 board:  <code>lmc1_Initial()</code>.<br>
    2）    Open test.ezd: <code>lmc1_LoadEzdFile(_T(“test.ezd”))</code>.<br>
    3）    Call lmc1_Mark() for machining: <code>lmc1_Mark()</code>.<br>
    4）    Close lmc1 board: <code>lmc1_Close()</code>.   </p>
  
  <p>d)  Fourth step, Release markezd.dll: <code>FreeLibrary(hEzdDLL)</code></p>
  
  <p>Bellow is the descriptions of the commands.</p>
  
  <p>lmc1_Initial<br>
  INTENTION: initialize lmc1 control board<br>
  DEFINITION: <code>int lmc1_Initial(TCHAR* strEzCadPath, BOOL bTestMode, HWND hOwenWnd)</code><br>
  strEzCadPath:  the full path where ezcad2.exe exists<br>
  bTestMode  Whether in test mode or not<br>
  hOwenWnd:  The window that has the focus. It is used to check the user’s stop messages. 
  DESCRIPTION: you must first call lmc1¬_Initial before other function in program.<br>
  RETURN VALUE: common error code </p>
  
  <p>lmc1_Close<br>
  INTENTION: Close lmc1 board<br>
  DEFINITION: <code>int lmc1_Close();</code><br>
  DESCRIPTION: you must call lmc1_Close to close the lmc1 board when exit program.<br>
  RETURN VALUE: common error code </p>
  
  <p>lmc1_LoadEzdFile<br>
  INTENTION: open the appointed ezd file, and clear all the object in database.<br>
  DEFINITION: <code>int lmc1_LoadEzdFile(TCHAR* strFileName);</code><br>
  DESCRIPTION: this function can open an ezd file that was build by user as a template. User need not set process parameters, because they will be loaded in from the template file.<br>
  RETURN VALUE: common error code </p>
  
  <p>lmc1_Mark<br>
  INTENTION: mark all the data in database<br>
  DEFINITION: <code>int lmc1_Mark(BOOL bFlyMark);</code><br>
  bFlyMark= TRUE  // mark on fly<br>
  DISCRIPTION: Begin to mark by calling this function after loading ezd file using lmc1_LoadEzdFile. The function will not return back until marking complete.<br>
  RETURN VALUE: common error code </p>
  
  <p>They also explain how to set up VS6.0</p>
  
  <ol>
  <li>Choose “Microsoft Visual C++ 6.0” when install visual studio, and click “Change Option”.</li>
  <li>Choose “VC++ MFC and Template Libraries” and click “Change Option”.</li>
  <li>Choose “MS Foundation Class Libraries” and click “change option”.</li>
  <li>Choose the options as following picture, and click “OK”.</li>
  <li>Open the project, choose menu Project->Settings. Choose “C/C++”, add “UNICODE” and delete “MCBS” in “Preprocessor definitions”</li>
  <li>Choose “Link”, select “Output” in Category, and add “wWinMainCRTStartup” in “Entry-point symbol”</li>
  <li>Change all “char” to “TCHAR” in source code.</li>
  <li>Change all character string included by double quotation marks “…” to _T(“…”)</li>
  <li>Compile and link the project again.</li>
  </ol>
  
  <p>most of the functions return an integer code of 0 for success.</p>
  
  <p>Would this be correct?</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using System.Runtime.InteropServices;
  
  
  namespace Start_Mark
  {
      public partial class Form1 : Form
      {
          [DllImport("kernel32.dll")]
          public static extern IntPtr LoadLibrary(string dllToLoad);
  
          [DllImport("kernel32.dll")]
          public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
  
          [DllImport("kernel32.dll")]
          public static extern bool FreeLibrary(IntPtr hModule);
  
          [DllImport("MarkEzd.dll")]
          [return: MarshalAs(UnmanagedType.I2)]
          public static extern int lmc1_Initial(string strEzCadPath, bool bTestMode, IntPtr hOwenWnd);
  
          [DllImport("MarkEzd.dll")]
          [return: MarshalAs(UnmanagedType.I2)]
          public static extern int lmc1_Close();
  
          [DllImport("MarkEzd.dll")]
          [return: MarshalAs(UnmanagedType.I2)]
          public static extern int lmc1_LoadEzdFile(string strFileName);
  
          [DllImport("MarkEzd.dll")]
          [return: MarshalAs(UnmanagedType.I2)]
          public static extern int lmc1_Mark(bool bFlyMark);
  
          public Form1()
          {
              InitializeComponent();
          }
  
          private void button1_Click(object sender, EventArgs e)
          {
              IntPtr hEzdDLL = LoadLibrary("MarkEzd.dll");
              IntPtr iplmc1_Initial = GetProcAddress(hEzdDLL, "lmc1_Initial");
              IntPtr iplmc1_Close = GetProcAddress(hEzdDLL, "lmc1_Close");
              IntPtr iplmc1_LoadEzdFile = GetProcAddress(hEzdDLL, "lmc1_LoadEzdFile");
              IntPtr iplmc1_Mark = GetProcAddress(hEzdDLL, "lmc1_Mark");
              int intlmc1_Initial=lmc1_Initial("c:\temp", false, hEzdDLL);
              if (intlmc1_Initial &gt; 0)
              {
                  return;
              }
              int intlmc1_LoadEzdFile = lmc1_LoadEzdFile("c:\temp\test.ezd");
              if (intlmc1_LoadEzdFile &gt; 0)
              {
                  return;
              }
              int intlmc1_Mark = lmc1_Mark(true);
              if (intlmc1_Mark &gt; 0)
              {
                  return;
              }
              int intlmc1_Close = lmc1_Close();
              if (intlmc1_Close &gt; 0)
              {
                  return;
              }
              FreeLibrary(hEzdDLL);
          }
      }
  }
  </code></pre>