title: C++ plugin for Unity "EntryPointNotFoundExeption"
body: <p>I need some serious help here... I'm trying to either get my member functions exported so I can call them in C#</p>
  
  <p><strong>WMIWrapper.h</strong></p>
  
  <pre><code>#ifndef _WMIWRAPPER_H_
  #define _WMIWRAPPER_H_
  
  #include &lt;Windows.h&gt;  
  #include &lt;sstream&gt;  
  #include &lt;iostream&gt;
  #include &lt;WbemCli.h&gt;  
  
  using std::endl;
  using std::wstring;
  using std::wstringstream;
  
  #pragma comment(lib, "wbemuuid.lib")  
  
  static class WMIWrapper 
  {  
  public:
      __declspec(dllexport) WMIWrapper();
      __declspec(dllexport) ~WMIWrapper();
  
      __declspec(dllexport) wstring CreateCOM();
      __declspec(dllexport) wstring CreateService();
  __declspec(dllexport) wstring GetMonitors();
  
  private:
      IWbemLocator* _locator;
      IWbemServices* _service;
      IEnumWbemClassObject* _monitors;
  };
  
  #endif
  </code></pre>
  
  <p><strong>WMIWrapper.cpp</strong></p>
  
  <pre><code>#include "WMIWrapper.h"
  
  
  extern "C" {
  
      WMIWrapper::WMIWrapper()
      {
          _locator = NULL;
          _service = NULL;
      }
  
      WMIWrapper::~WMIWrapper()
      {
          if(_service != NULL)
              _service-&gt;Release();
          if(_locator != NULL)
              _locator-&gt;Release();
      }
  
      wstring WMIWrapper::CreateCOM()
      {
          wstringstream ERRStream (wstringstream::in | wstringstream::out);
          HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);  
          if(FAILED(hRes))  
          {  
              ERRStream &lt;&lt; "Unable to launch COM: 0x" &lt;&lt; std::hex &lt;&lt; hRes &lt;&lt; endl;
              return L"";  
          }  
  
          hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);
          if(FAILED(hRes))
          {
              ERRStream &lt;&lt; "Unable to set security level for COM: " &lt;&lt; std::hex &lt;&lt; hRes &lt;&lt; endl;
              return L"";
          }
  
          if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&amp;_locator))))  
          {  
              ERRStream &lt;&lt; "Unable to create a WbemLocator: " &lt;&lt; std::hex &lt;&lt; hRes &lt;&lt; endl;  
              return L"";  
          }
  
          const std::wstring&amp; myWString = ERRStream.str();
          const LPCWSTR p = myWString.c_str();
          return p;
  
      }
  
      wstring WMIWrapper::CreateService()
      {
          wstringstream ERRStream (wstringstream::in | wstringstream::out);
          HRESULT hRes;
          if(_locator == NULL || FAILED(hRes = _locator-&gt;ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &amp;_service)))  
          {  
              ERRStream &lt;&lt; "Unable to connect to \"CIMV2\": " &lt;&lt; std::hex &lt;&lt; hRes &lt;&lt; endl;  
              return L"";  
          }  
  
          const std::wstring&amp; myWString = ERRStream.str();
          const LPCWSTR p = myWString.c_str();
          return p;
      }
  
      wstring WMIWrapper::GetMonitors()
      {
          HRESULT hRes;
          wstringstream ssMonitorDescription;
          if(_locator == NULL 
              || _service == NULL
              || FAILED(hRes = _service-&gt;ExecQuery(L"WQL", L"SELECT * FROM Win32_DesktopMonitor", WBEM_FLAG_FORWARD_ONLY, NULL, &amp;_monitors)))
          {
              //ERRStream &lt;&lt; "Unable to retrieve desktop monitors: " &lt;&lt; std::hex &lt;&lt; hRes &lt;&lt; endl;
              return L"";
          }
  
          IWbemClassObject* clsObj = NULL;
          int numElems;
          while((hRes = _monitors-&gt;Next(WBEM_INFINITE, 1, &amp;clsObj, (ULONG*)&amp;numElems)) != WBEM_S_FALSE)
          {
              if(FAILED(hRes))
                  break;
  
              VARIANT vRet;
              VariantInit(&amp;vRet);
              if(SUCCEEDED(clsObj-&gt;Get(L"Description", 0, &amp;vRet, NULL, NULL)) &amp;&amp; vRet.vt == VT_BSTR)
              {
                  //std::wcout &lt;&lt;  L"Description: " &lt;&lt; vRet.bstrVal &lt;&lt; endl;
                  ssMonitorDescription &lt;&lt; "Description: " &lt;&lt; vRet.bstrVal &lt;&lt; endl;
                  VariantClear(&amp;vRet);
              }
          }
  
          clsObj-&gt;Release();
  
          return ssMonitorDescription.str();
      }
  }
  </code></pre>
  
  <p><strong>Interface.cpp</strong></p>
  
  <pre><code>#include "WMIWrapper.h"
  
  extern "C" 
  {
      __declspec( dllexport ) wstring GetMonitor()
      {
          WMIWrapper* wmiWrapper = new WMIWrapper();
          wmiWrapper-&gt;CreateCOM();
          wmiWrapper-&gt;CreateServiceW();
          return wmiWrapper-&gt;GetMonitors();
      }
  }
  </code></pre>
  
  <p><strong>Unity Script</strong></p>
  
  <pre><code>using UnityEngine;
  using System.Runtime.InteropServices;
  using System;
  
  
  public class HardwareDiagnostics : MonoBehaviour {
  
      //[DllImport("WMIWrapper", EntryPoint="CreateCOM", CharSet = CharSet.Unicode)]
      //static extern String CreateCOM();
      //
      //[DllImport("WMIWrapper", EntryPoint="CreateService", CharSet = CharSet.Unicode)]
      //static extern String CreateService();
      //
      //[DllImport("WMIWrapper", EntryPoint="GetMonitors", CharSet = CharSet.Unicode)]
      //static extern String GetMonitors();
      [DllImport("WMIWrapper", EntryPoint = "GetMonitor", CharSet = CharSet.Unicode)]
      static extern string GetMonitor();
  
      // Use this for initialization
      void Start () {
          Debug.Log(GetMonitor());
          Debug.Log ("Cock");
  
      }
  
      // Update is called once per frame
      void Update () {
  
      }
  
  
  }
  </code></pre>
  
  <p>So I'm trying to call those member functions from the Unity script and I'm getting the <em>EntryPointNotFoundExeption</em> error. I thought maybe it was because you couldn't export member functions, so I tried writing that "Interface.cpp" to execute those functions and return the result but that returns the same error.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Per suggestion I have changed my C++ functions to this format</p>
  
  <pre><code>void WMIWrapper::CreateCOM(wchar_t* err, int errLength)
      {
          .../Determine wstringstream ERRStream
  
  
          wcscpy_s(err, errLength, ERRStream.str().c_str());
  
      }
  </code></pre>
  
  <p>And my C# like so:</p>
  
  <pre><code>public class HardwareDiagnostics : MonoBehaviour {
  
      [DllImport( "WMIWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
      private static extern void CreateCOM(StringBuilder str, int length);
  
      [DllImport( "WMIWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
      private static extern void CreateService(StringBuilder str, int length);
  
      [DllImport( "WMIWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
      private static extern void GetMonitors(StringBuilder str, int length);
  
      // Use this for initialization
      void Start () {
          StringBuilder buffer = new StringBuilder(255);
  
          CreateCOM(buffer, buffer.Capacity);
          Debug.Log(buffer.ToString());
  
          CreateService(buffer, buffer.Capacity);
          Debug.Log(buffer.ToString());
  
          GetMonitors(buffer, buffer.Capacity);
          Debug.Log(buffer.ToString());
  
      }
  
      // Update is called once per frame
      void Update () {
  
      }
  
  
  }
  </code></pre>
  
  <p>HOWEVER, I'm still getting  "EntryPointNotFoundExeption" when calling the first function, CreateCOM();</p>